打开 Window 时,如何将数据模板化的文本框聚焦在 Window 中 ItemsControl 的第一个元素中? (C#, WPF)
How to focus a datatemplated TextBox in the first element of an ItemsControl in a Window, when the Window is opened? (C#, WPF)
当用户单击应用程序中的按钮时,会打开一个 window。我希望属于 ItemsControl 中第一项的 TextBox 获得焦点,以便用户可以在 Window 打开后立即开始键入,而无需手动 select TextBox。
如何做到这一点?
为简单起见,我们可以说 Window 大致如下所示:
<Window>
<Grid>
<ItemsControl ItemsSource="{Binding MyItems}">
<DataTemplate>
<Grid>
<StackPanel>
<StackPanel>
<customControls:ValidationControl>
<TextBox Text="" />
</customControls:ValidationControl>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl>
</Grid>
</Window>
更新
在查看了建议的答案和这个 link 之后:
Window Loaded and WPF
修改后的解决方案如下:
<Window>
<Grid>
<ItemsControl x:Name="myItemsControl" ItemsSource="{Binding MyItems}">
<DataTemplate>
<Grid>
<StackPanel>
<StackPanel>
<customControls:ValidationControl>
<TextBox Text="" />
</customControls:ValidationControl>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl>
</Grid>
</Window>
在构造函数中:
this.Loaded += new RoutedEventHandler(ThisWindowLoaded);
加载方法:
private void ThisWindowLoaded(object sender, RoutedEventArgs e)
{
var textbox = FindVisualChild<TextBox>(myItemsControl.ItemContainerGenerator.ContainerFromIndex(0));
FocusManager.SetFocusedElement(myItemsControl, textbox);
}
超级骗子方法:
public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null)
return childItem;
}
}
return null;
}
如果是 WPF 你应该像下面那样做 smt :
<Grid>
<DataGridCell>
<Grid>
<TextBox x:Name="TextBox1" Text=" ">
</TextBox>
</Grid>
</DataGridCell>
</Grid>
和代码隐藏:
TextBox1.Focus();
FocusManager.SetFocusedElement() 可能就是您要查找的内容。
Xaml
<ItemsControl x:Name="ItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
在 Loaded 事件中,您关注第一个文本框:
var textbox = ItemsControl.ItemContainerGenerator.ContainerFromIndex(0).FindChildByType<TextBox>();
FocusManager.SetFocusedElement(ItemsControl, textbox);
以下是我先找到的方法child:
public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null
&& child is T)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null)
return childItem;
}
}
return null;
}
如果有人对以下内容感兴趣:
在我的情况下,ItemsControl 有几个不同的 DataTemplates 用于不同类型的项目。有些是可编辑的,有些不是。这就是为什么我无法判断当前在哪个项目中显示哪种编辑器。
所以我在寻找不同的解决方案:
我注意到,当我按一次 Tab 键时(在对话框打开后),焦点移动到 ItemsControl 中的预期元素。
这就是为什么我在加载事件中生成一个选项卡:
this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)delegate
{
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
});
当用户单击应用程序中的按钮时,会打开一个 window。我希望属于 ItemsControl 中第一项的 TextBox 获得焦点,以便用户可以在 Window 打开后立即开始键入,而无需手动 select TextBox。
如何做到这一点?
为简单起见,我们可以说 Window 大致如下所示:
<Window>
<Grid>
<ItemsControl ItemsSource="{Binding MyItems}">
<DataTemplate>
<Grid>
<StackPanel>
<StackPanel>
<customControls:ValidationControl>
<TextBox Text="" />
</customControls:ValidationControl>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl>
</Grid>
</Window>
更新 在查看了建议的答案和这个 link 之后: Window Loaded and WPF 修改后的解决方案如下:
<Window>
<Grid>
<ItemsControl x:Name="myItemsControl" ItemsSource="{Binding MyItems}">
<DataTemplate>
<Grid>
<StackPanel>
<StackPanel>
<customControls:ValidationControl>
<TextBox Text="" />
</customControls:ValidationControl>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl>
</Grid>
</Window>
在构造函数中:
this.Loaded += new RoutedEventHandler(ThisWindowLoaded);
加载方法:
private void ThisWindowLoaded(object sender, RoutedEventArgs e)
{
var textbox = FindVisualChild<TextBox>(myItemsControl.ItemContainerGenerator.ContainerFromIndex(0));
FocusManager.SetFocusedElement(myItemsControl, textbox);
}
超级骗子方法:
public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null)
return childItem;
}
}
return null;
}
如果是 WPF 你应该像下面那样做 smt :
<Grid>
<DataGridCell>
<Grid>
<TextBox x:Name="TextBox1" Text=" ">
</TextBox>
</Grid>
</DataGridCell>
</Grid>
和代码隐藏:
TextBox1.Focus();
FocusManager.SetFocusedElement() 可能就是您要查找的内容。
Xaml
<ItemsControl x:Name="ItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
在 Loaded 事件中,您关注第一个文本框:
var textbox = ItemsControl.ItemContainerGenerator.ContainerFromIndex(0).FindChildByType<TextBox>();
FocusManager.SetFocusedElement(ItemsControl, textbox);
以下是我先找到的方法child:
public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null
&& child is T)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null)
return childItem;
}
}
return null;
}
如果有人对以下内容感兴趣: 在我的情况下,ItemsControl 有几个不同的 DataTemplates 用于不同类型的项目。有些是可编辑的,有些不是。这就是为什么我无法判断当前在哪个项目中显示哪种编辑器。 所以我在寻找不同的解决方案: 我注意到,当我按一次 Tab 键时(在对话框打开后),焦点移动到 ItemsControl 中的预期元素。 这就是为什么我在加载事件中生成一个选项卡:
this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)delegate
{
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
});