web-dev-qa-db-fra.com

WPF: comment supprimer par programme le focus d'un TextBox

Je veux ajouter un comportement simple (du moins je le pensais) à mon WPF TextBox.

Lorsque l'utilisateur appuie sur Échap, je veux que le TextBox qu'il modifie ait le texte qu'il avait lorsque l'utilisateur a commencé à le modifier, ET je veux supprimer le focus du TextBox.

Je n'ai aucun problème à définir le texte pour la valeur qu'il avait au début de l'édition.

Le problème est de supprimer le focus de l'élément. Je ne veux pas déplacer le focus vers un autre composant, je veux juste que le TextBox perde le focus. Dois-je avoir un élément invisible pour définir le focus afin que mon TextBox puisse perdre le focus?

83
jpsstavares

dans .NET Framework 4 juste Keyboard.ClearFocus();

132
LPL

Le code que j'utilise:

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

Un peu tard pour la fête, mais cela m'a été utile alors voilà.

Depuis .Net 3.0, FrameworkElement a une fonction MoveFocus qui a fait l'affaire pour moi.

18
SuperOli

Vous pouvez définir le focus sur un ancêtre focusable. Ce code fonctionnera même si la zone de texte est à l'intérieur d'un modèle sans ancêtre focalisable à l'intérieur de ce même modèle:

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

    ancestor = VisualTreeHelper.GetParent(ancestor);
}
9
Julian Dominguez

AFAIK, il n'est pas possible de supprimer complètement la mise au point. Quelque chose dans votre fenêtre aura toujours le focus.

6
bitbonk

Étant donné qu'aucune des réponses ci-dessus n'a fonctionné pour moi et que la réponse acceptée ne fonctionne que pour un focus clavier, je suis parvenu à l'approche suivante:

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

Tue les deux, logique ainsi que la mise au point du clavier.

4
Cyclone

Dans le développement de Windows Phone, je viens de faire Focus() ou this.Focus() dans PhoneApplicationPage et cela a fonctionné comme un charme.

1
Bruno Lemos

Pour moi, c'est assez délicat, surtout lors de l'utilisation avec la liaison LostFocus. Cependant, ma solution consiste à ajouter une étiquette vide et à se concentrer dessus.

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

...

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

Ma réponse ne répond pas directement à la question ci-dessus, cependant, je pense que le libellé de celle-ci l'a fait devenir "La Question" sur la suppression programmatique de la concentration. Un scénario courant où cela est nécessaire est que l'utilisateur puisse effacer le focus en cliquant avec le bouton gauche sur l'arrière-plan d'un contrôle racine, comme une fenêtre.

Donc, pour y parvenir, vous pouvez créer un comportement attaché qui basculera le focus vers un contrôle créé dynamiquement (dans mon cas, une étiquette vide). Il est préférable d'utiliser ce comportement sur les éléments de plus haut niveau comme les fenêtres, car il parcourt ses enfants pour trouver un panneau auquel il peut ajouter une étiquette factice.

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
Artem K