【问题标题】:Set Focus on parent TabItem in WPF在 WPF 中将焦点设置在父 TabItem 上
【发布时间】:2021-05-03 17:06:51
【问题描述】:

有没有办法自动切换到承载我想要关注的控件的 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 中的其他级别。有可能吗?

顺便说一句,如果有帮助,此类功能的应用会将焦点设置在通过错误验证突出显示的控件上和/或切换到包含它的窗格。

【问题讨论】:

    标签: c# wpf setfocus


    【解决方案1】:

    您可以使用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();
    }
    

    【讨论】:

    • 谢谢@Dakota,但这没有用。我最好的猜测是,当未选择父 TabItem 时, SomeTextBox 会从 VisualTree 中删除。
    • 很好,我在答案的底部添加了另一种方法。它更容易出错,所以如果您开始使用复杂的布局,请小心。
    • 只剩下一个小细节:选择父容器后,需要一个UpdateLayout,否则Focus 不起作用。请为其他用户添加。感谢您对复杂布局的提醒,我会根据自己的需要进行调整。我将把它放在我的 ViewFactory 中并寻找需要选择的容器。做得好。感谢您的帮助。
    • 作为脚注,可以使用 LogicalTreeHelper 而不是 VisualTreeHelp。
    猜你喜欢
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 2011-02-21
    • 2010-11-23
    • 2011-06-25
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多