WPF: как программно удалить фокус из TextBox

Я хочу добавить к моему WPF TextBox простое (по крайней мере, я думал, это было) поведение.

Когда пользователь нажимает Escape, я хочу, чтобы TextBox он редактировал текст, который у него был, когда пользователь начал редактировать, и я хочу удалить фокус из TextBox.

У меня нет проблем с установкой текста для значения, которое оно имело в начале редактирования.

Проблема заключается в удалении фокуса элемента. Я не хочу переместить фокус на любой другой компонент, я просто хочу, чтобы TextBox потерял фокус. Должен ли я иметь невидимый элемент для установки фокуса, чтобы мой TextBox мог потерять фокус?

Ответ 2

Код, который я использовал:

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

Ответ 3

Немного поздно для вечеринки, но это было полезно для меня, поэтому вот оно.

Так как .Net 3.0, FrameworkElement имеет функцию MoveFocus, которая сделала трюк для меня.

Ответ 4

Вы можете установить фокус на фокусируемого предка. Этот код будет работать, даже если текстовое поле находится внутри шаблона без ориентированных предков внутри того же шаблона:

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

    ancestor = VisualTreeHelper.GetParent(ancestor);
}

Ответ 5

AFAIK, невозможно полностью удалить фокус. Что-то в вашем окне всегда будет иметь фокус.

Ответ 6

В Windows Phone Development я просто сделал Focus() или this.Focus() в PhoneApplicationPage, и он работал как шарм.

Ответ 7

Поскольку ни один из приведенных выше ответов не работал для меня, и принятый ответ работает только для клавиатуры, я пришел к следующему подходу:

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

Убивает как логический, так и фокус клавиатуры.

Ответ 8

Для меня это довольно сложно, особенно при использовании с привязкой LostFocus. Однако мой обходной путь - добавить пустой ярлык и сосредоточиться на нем.

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

...

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

Ответ 9

Мой ответ не затрагивает вышеуказанный вопрос напрямую, однако я чувствую, что его формулировка заставила его стать "Вопросом" о программном избавлении от фокуса. Обычный сценарий, в котором это необходимо, заключается в том, чтобы пользователь мог фокусироваться на щелчке левой кнопкой мыши по фону корневого элемента управления, например окна.

Таким образом, чтобы достичь этого, вы можете создать Attached Behavior, который переключит фокус на динамически создаваемый элемент управления (в моем случае, пустую метку). Желательно использовать это поведение на элементах самого высокого уровня, таких как окна, так как он просматривает дочерние элементы, чтобы найти панель, к которой можно добавить фиктивную метку.

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

Ответ 10

Keyboard.ClearFocus(); - путь.