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?
dans .NET Framework 4 juste Keyboard.ClearFocus();
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);
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.
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);
}
AFAIK, il n'est pas possible de supprimer complètement la mise au point. Quelque chose dans votre fenêtre aura toujours le focus.
É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.
Dans le développement de Windows Phone, je viens de faire Focus()
ou this.Focus()
dans PhoneApplicationPage et cela a fonctionné comme un charme.
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();
}
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();
}
}