问题描述
有没有办法自动切换到承载我想要关注的控件的 TabItem?
我的示例窗口来举例说明问题。
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Sample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style targettype="Button">
<Setter Property="Width" Value="80"/>
<Setter Property="Height" Value="24"/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDeFinitions>
<RowDeFinition Height="*"/>
<RowDeFinition Height="auto"/>
</Grid.RowDeFinitions>
<TabControl Grid.Row="0" Margin="10" Background="White">
<TabItem Header="TabItem1">
<Button x:Name="SomeButton" Content="Set Focus on TextBox" Width="120" Click="Button_Click"/>
</TabItem>
<TabItem Header="TabItem2">
<TextBox x:Name="SomeTextBox" Margin="10" Text="Sample text"/>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Margin="10">
<Button Content="Cancel" HorizontalAlignment="Right" Click="Button_Click_1"/>
</StackPanel>
</Grid>
</Window>
以及背后的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender,RoutedEventArgs e)
{
SomeTextBox.Focus();
}
private void Button_Click_1(object sender,RoutedEventArgs e)
{
Close();
}
}
因此,当单击 SomeButton
时,我想将焦点移至 SomeTextBox
,但要使其起作用,我必须先选择 TabItem2
。在提供的示例中,这显然很容易,但我正在寻找一种自动化解决方案,它“知道”SomeTextBox
属于 TabItem2
并切换到它,然后将焦点设置在所需的控件上。不用说,在实际情况下,SomeTextBox
可能位于其他类型窗格中 VisualTree
的其他级别。可能吗?
顺便说一句,如果有帮助,这种功能的应用程序会将焦点设置在错误验证突出显示的控件上和/或切换到包含它的窗格。
解决方法
您可以使用 VisualTreeHelper
类查找特定类型的最近父级。
这是来自 This answer 的一个实现示例。
public static T FindParentOfType<T>(this DependencyObject child) where T : DependencyObject
{
DependencyObject parentDepObj = child;
do
{
parentDepObj = VisualTreeHelper.GetParent(parentDepObj);
T parent = parentDepObj as T;
if (parent != null) return parent;
}
while (parentDepObj != null);
return null;
}
获得对 TabItem
的引用后,您可以设置其 IsSelected
属性以在 TabControl
中选择它。
private void Button_Click(object sender,RoutedEventArgs e)
{
var tabItem = FindParentOfType<TabItem>(SomeTextBox);
if (tabItem is null) return;
(tabItem as TabItem).IsSelected = true;
SomeTextBox.Focus();
}
编辑
很好地抓住了 TextBox
不在可视化树中而其父 TabItem
未被选中的情况。这是获取不依赖于可视化树的 TextBox
的另一种方法。
private void Button_Click(object sender,RoutedEventArgs e)
{
FrameworkElement currentItem = SomeTextBox;
do
{
currentItem = (FrameworkElement)currentItem.Parent;
}
while (!(currentItem is TabItem)
&& (currentItem as TabItem).Parent != MyTabControl // Optional handling in case you have nested TabControls
&& !(currentItem.Parent is null));
(currentItem as TabItem).IsSelected = true;
currentItem.UpdateLayout();
SomeTextBox.Focus();
}