WPF:如何以编程方式从文本框中移除焦点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2914495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:48:25  来源:igfitidea点击:

WPF: How to programmatically remove focus from a TextBox

wpftextboxfocus

提问by jpsstavares

I want to add a simple (at least I thought it was) behaviour to my WPF TextBox.

我想向我的 WPF 添加一个简单的(至少我认为是)行为TextBox

When the user presses Escape I want the TextBoxhe is editing to have the text it had when the user started editing, AND I want to remove the focus from the TextBox.

当用户按下 Escape 时,我希望TextBox他正在编辑的文本具有用户开始编辑时的文本,并且我想从TextBox.

I don't have any problem setting the text for the value it had in the beginning of the edit.

我在为编辑开始时的值设置文本时没有任何问题。

The problem is to remove the focus of the element. I don't want to move the focus to any other component, I just want the TextBoxto lose focus. Will I have to have an invisible element to set the focus so my TextBoxcan lose focus?

问题是移除元素的焦点。我不想将焦点移到任何其他组件上,我只想让TextBox焦点失去焦点。我是否必须有一个不可见的元素来设置焦点,以便我TextBox可以失去焦点?

回答by LPL

in .NET Framework 4 just Keyboard.ClearFocus();

在 .NET Framework 4 中 Keyboard.ClearFocus();

回答by decasteljau

The code I have been using :

我一直在使用的代码:

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

回答by SuperOli

A bit late to the party, but it was helpful to me so here it goes.

聚会有点晚了,但这对我很有帮助,所以就这样吧。

Since .Net 3.0, FrameworkElementhas a MoveFocusfunction which did the trick for me.

从 .Net 3.0 开始,FrameworkElement有一个MoveFocus功能,它对我有用。

回答by Julian Dominguez

You can set the focus to a focusable ancestor. This code will work even if the textbox is inside a template with no focusable ancestors inside that same template:

您可以将焦点设置为可聚焦的祖先。即使文本框位于同一个模板中没有可聚焦祖先的模板中,此代码也能正常工作:

DependencyObject ancestor = textbox.Parent;
while (ancestor != null)
{
    var element = ancestor as UIElement;
    if (element != null && element.Focusable)
    {
        element.Focus();
        break;
    }

    ancestor = VisualTreeHelper.GetParent(ancestor);
}

回答by Cyclone

Since none of the above answers worked for me and the accepted answer does work only for a keyboard focus, I came to the following approach:

由于上述答案都不适用于我,并且接受的答案仅适用于键盘焦点,因此我采用了以下方法:

// Kill logical focus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(textBox), null);
// Kill keyboard focus
Keyboard.ClearFocus();

Kills both, logical as well as the keyboard focus.

杀死两者,逻辑以及键盘焦点。

回答by bitbonk

AFAIK, it is not possible to completely remove the focus. Something in your Window will always have the focus.

AFAIK,不可能完全去除焦点。窗口中的某些内容将始终是焦点。

回答by Bruno Lemos

In Windows Phone Development, I just did Focus()or this.Focus()in the PhoneApplicationPageand it worked like a charm.

在Windows Phone开发,我只是做 Focus()this.Focus()的PhoneApplicationPage和它的工作就像一个魅力。

回答by Brian Ng

For me, it's quite tricky, especially when using with LostFocus binding. However, my workaround is to add an empty label and focus on it.

对我来说,这很棘手,尤其是在使用 LostFocus 绑定时。但是,我的解决方法是添加一个空标签并专注于它。

<Label Name="ResetFocusArea" Focusable="True" FocusVisualStyle="{x:Null}" />

...

...

OnKeyDown(object sender, RoutedEventArgs e)
{
  //if is Esc
  ResetFocusArea.Focus();
}

回答by TripleAccretion

My answer does not adress the above question directly, however, I feel that the wording of it has caused it to become "The Question" about programmatically getting rid of focus. A common scenario where this is needed is for the user to be able to clear focus upon left-clicking the background of a root control, like window.

我的回答没有直接解决上述问题,但是,我觉得它的措辞使其成为关于以编程方式摆脱焦点的“问题”。需要这样做的常见场景是用户能够在左键单击根控件(如窗口)的背景时清除焦点。

So, to achieve this, you can create an Attached Behavior that will switch focus to a dynamically created control (in my case, an empty label). It is preferrable to use this behavior on the highest-level elements like windows, as it iterates through it's children to find a panel it can add a dummy label to.

因此,为了实现这一点,您可以创建一个附加行为,它将焦点切换到动态创建的控件(在我的例子中,是一个空标签)。最好在窗口之类的最高级别元素上使用此行为,因为它会遍历它的子元素以找到可以为其添加虚拟标签的面板。

public class LoseFocusOnLeftClick : Behavior<FrameworkElement>
{
    private readonly MouseBinding _leftClick;
    private readonly Label _emptyControl = new Label() { Focusable = true, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top };

    public LoseFocusOnLeftClick()
    {
        _leftClick = new MouseBinding(new RelayCommand(LoseFocus), new MouseGesture(MouseAction.LeftClick));
    }

    protected override void OnAttached()
    {
        AssociatedObject.InputBindings.Add(_leftClick);
        AssociatedObject.Loaded += AssociatedObject_Loaded;
    }        

    protected override void OnDetaching()
    {
        AssociatedObject.InputBindings.Remove(_leftClick);
        AssociatedObject.Loaded -= AssociatedObject_Loaded;
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        AssociatedObject.Loaded -= AssociatedObject_Loaded;

        AttachEmptyControl();
    }

    private void AttachEmptyControl()
    {            
        DependencyObject currentElement = AssociatedObject;
        while (!(currentElement is Panel))
        {
            currentElement = VisualTreeHelper.GetChild(currentElement, 0);
        }

        ((Panel)currentElement).Children.Add(_emptyControl);
    }

    private void LoseFocus()
    {            
        _emptyControl.Focus();
    }
}