将焦点设置回其父级?

时间:2014-02-21 12:19:28

标签: c# wpf xaml focus setfocus

从帖子WPF: How to programmatically remove focus from a 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等其他项目。

2 个答案:

答案 0 :(得分:2)

是的,在这种情况下,有可能实施attached行为。使用焦点的逻辑必须适合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
}
  

项目可在此link获得。

答案 1 :(得分:2)

应该相对简单:

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);

这是有效的,因为所有控件都继承自继承自DependencyObject的FrameworkElement。因此,您可以将ctrl设置为您想要的任何类型的控件:ComboBoxTextBoxButtonCanvas等。