WPF: Как программно удалить фокус из TextBox - PullRequest
80 голосов
/ 26 мая 2010

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

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

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

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

Ответы [ 9 ]

127 голосов
/ 09 января 2012

в .NET Framework 4 просто Keyboard.ClearFocus();

50 голосов
/ 26 мая 2010

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

// 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);
17 голосов
/ 02 октября 2013

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

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

9 голосов
/ 05 ноября 2010

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

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

    ancestor = VisualTreeHelper.GetParent(ancestor);
}
6 голосов
/ 26 мая 2010

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

4 голосов
/ 18 мая 2019

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

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

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

1 голос
/ 15 июня 2014

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

0 голосов
/ 10 мая 2019

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

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

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();
    }
}
0 голосов
/ 18 апреля 2019

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

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

...

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