WPF: How to programmatically remove focus from a TextBox

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

When the user presses Escape I want the TextBox he is editing to have the text it had when the user started editing, AND I want to remove the focus from the 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 TextBox to lose focus. Will I have to have an invisible element to set the focus so my TextBox can lose focus?

Answers


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


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

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

Since .Net 3.0, FrameworkElement has a MoveFocus function which did the trick for me.


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

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


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.


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


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.

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

...

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

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

Need Your Help

Error in Fragment: "Already managing a GoogleApiClient with id 0"

java android android-fragments

Everything works right the first time, if you launch a second time you see this error:

ehcache configuration in Spring framework

spring ehcache spring-4 spring-cache

I am trying to load some context from an RSS feed and pass it as a cache to the client using ehcache library in spring. here is my code :