将焦点设置回其父元素?

3

从这篇帖子WPF:如何以编程方式从TextBox中移除焦点,我知道如何使用以下代码将TextBox的焦点设置回其父级:

// Move to a parent that can take focus
FrameworkElement parent = (FrameworkElement)textBox.Parent;
while (parent != null && parent is IInputElement 
                      && !((IInputElement)parent).Focusable)
{
    parent = (FrameworkElement)parent.Parent;
}

DependencyObject scope = FocusManager.GetFocusScope(textBox);
FocusManager.SetFocusedElement(scope, parent as IInputElement);

有没有一种方法可以将这个代码(如模板函数)泛化,使其也适用于其他项目,如ComboBoxCanvasImage等?


只是一个想法,传递控件类型的对象而不是文本框对象怎么样? - samar
2个回答

3

这应该相对简单:

FrameworkElement ctrl = control; //or whatever you're passing in, since all controls are FrameworkElements.

// Move to a parent that can take focus
FrameworkElement parent = (FrameworkElement)ctrl.Parent;
while (parent != null && parent is IInputElement 
                  && !((IInputElement)parent).Focusable)
{
    parent = (FrameworkElement)parent.Parent;
}

DependencyObject scope = FocusManager.GetFocusScope(ctrl); //can pass in ctrl here because FrameworkElement inherits from DependencyObject
FocusManager.SetFocusedElement(scope, parent as IInputElement);

这是因为所有的控件都继承自FrameworkElement,而FrameworkElement又继承自DependencyObject。所以你可以将ctrl设置为任何类型的控件,比如:ComboBoxTextBoxButtonCanvas等等。

解决了我长期存在的专注问题,真是救了我的命。 - undefined

2

有这样一种可能性,在这种情况下,可以实现附加行为。处理具有焦点的工作逻辑必须适配DependencyPropertyChangedEvent处理程序。

这里是您所需案例的示例:

XAML

<Window x:Class="RemoveFocusHelp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:this="clr-namespace:RemoveFocusHelp"
        WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <TextBox Name="TestTextBox"
                 this:RemoveFocusBehavior.IsRemoveFocus="False"
                 Width="100"
                 Height="25"
                 Text="TestText" />        

        <Button Name="CreateFocus" 
                Width="100" 
                Height="30" 
                Content="Create Focus"
                HorizontalAlignment="Left" 
                Click="CreateFocus_Click" />

        <Button Name="RemoveFocus" 
                Focusable="False" 
                Width="100" 
                Height="30" 
                Content="Remove Focus"
                HorizontalAlignment="Right" 
                Click="RemoveFocus_Click" />
    </Grid>
</Window>

Code-behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void CreateFocus_Click(object sender, RoutedEventArgs e)
    {
        TestTextBox.Focus();
    }

    private void RemoveFocus_Click(object sender, RoutedEventArgs e)
    {
        RemoveFocusBehavior.SetIsRemoveFocus(TestTextBox, true);
    }
}

public class RemoveFocusBehavior
{
    #region IsRemoveFocus Dependency Property

    public static readonly DependencyProperty IsRemoveFocusProperty;

    public static void SetIsRemoveFocus(DependencyObject DepObject, bool value)
    {
        DepObject.SetValue(IsRemoveFocusProperty, value);
    }

    public static bool GetIsRemoveFocus(DependencyObject DepObject)
    {
        return (bool)DepObject.GetValue(IsRemoveFocusProperty);
    }

    static RemoveFocusBehavior()
    {
        IsRemoveFocusProperty = DependencyProperty.RegisterAttached("IsRemoveFocus",
                                                            typeof(bool),
                                                            typeof(RemoveFocusBehavior),
                                                            new UIPropertyMetadata(false, IsRemoveFocusTurn));
    }

    #endregion

    #region IsRemoveFocus Property Metadata

    private static void IsRemoveFocusTurn(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        Control control = sender as Control;

        if (control == null) 
        {
            return;
        }

        if (e.NewValue is bool && ((bool)e.NewValue) == true)
        {
            FrameworkElement parent = (FrameworkElement)control.Parent;

            while (parent != null && parent is IInputElement
                                  && !((IInputElement)parent).Focusable)
            {
                parent = (FrameworkElement)parent.Parent;
            }

            DependencyObject scope = FocusManager.GetFocusScope(control);
            FocusManager.SetFocusedElement(scope, parent as IInputElement);
        }
    }

    #endregion
}

该项目可以在此链接中获取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接