WPF – Définir le focus lorsque l’utilisateur clique sur un bouton – Aucun code derrière

Est-il possible de définir le Focus d’un contrôle à un autre à l’aide de WPF Trigger s?

Comme dans l’exemple suivant:

              

Existe-t-il un moyen pour cet EventTrigger de se concentrer sur le textBox “txtName”?

J’essaie de trouver le moyen de faire quelque chose comme ça en utilisant un MVVM ssortingct. Si c’est quelque chose qui ne devrait pas être fait via le XAML (dans MVVM), alors c’est très bien. Mais j’aimerais voir une sorte de documentation sur la manière dont elle s’insère dans le modèle MVVM en dehors du XAML.

Avez-vous envisagé d’utiliser un comportement attaché. Ils sont simples à mettre en œuvre et à utiliser AttachedProperty. Bien qu’il ait encore besoin de code, ce code est extrait d’une classe et réutilisé. Ils peuvent éliminer le besoin de “code derrière” et sont souvent utilisés avec le modèle MVVM.

Essayez celui-ci et voyez si cela fonctionne pour vous.

 public class EventFocusAttachment { public static Control GetElementToFocus(Button button) { return (Control)button.GetValue(ElementToFocusProperty); } public static void SetElementToFocus(Button button, Control value) { button.SetValue(ElementToFocusProperty, value); } public static readonly DependencyProperty ElementToFocusProperty = DependencyProperty.RegisterAttached("ElementToFocus", typeof(Control), typeof(EventFocusAttachment), new UIPropertyMetadata(null, ElementToFocusPropertyChanged)); public static void ElementToFocusPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var button = sender as Button; if (button != null) { button.Click += (s, args) => { Control control = GetElementToFocus(button); if (control != null) { control.Focus(); } }; } } } 

Et ensuite, dans votre XAML, faites quelque chose comme …

   

Je ne suis pas près du studio visuel, donc je ne peux pas vraiment essayer ceci pour le moment, mais vous devriez pouvoir faire quelque chose comme ceci:

 FocusManager.FocusedElement="{Binding ElementName=txtName}"> 

Modifier:

Il y a une question complémentaire (posée plus récemment) à ce sujet ici: Comment définir l’autofocus uniquement dans xaml? qui contient cette méthode et quelques idées différentes sur son utilisation.

Vous pouvez également utiliser un comportement WPF …

  public class FocusElementAfterClickBehavior : Behavior { private ButtonBase _AssociatedButton; protected override void OnAttached() { _AssociatedButton = AssociatedObject; _AssociatedButton.Click += AssociatedButtonClick; } protected override void OnDetaching() { _AssociatedButton.Click -= AssociatedButtonClick; } void AssociatedButtonClick(object sender, RoutedEventArgs e) { Keyboard.Focus(FocusElement); } public Control FocusElement { get { return (Control)GetValue(FocusElementProperty); } set { SetValue(FocusElementProperty, value); } } // Using a DependencyProperty as the backing store for FocusElement. This enables animation, styling, binding, etc... public static readonly DependencyProperty FocusElementProperty = DependencyProperty.Register("FocusElement", typeof(Control), typeof(FocusElementAfterClickBehavior), new UIPropertyMetadata()); } 

Voici le code XAML pour utiliser le comportement.

Inclure les espaces de noms:

 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:local="clr-namespace:WpfApplication1" 

Attachez le comportement WPF au bouton et liez l’élément sur lequel vous souhaitez définir le focus:

   

Donc, de cette façon, vous n’avez pas de code derrière et il est réutilisable sur tout contrôle hérité de ButtonBase.

J’espère que ça aide quelqu’un.

vous avez besoin d’un TriggerAction pour appeler la méthode Focus () sur le contrôle souhaité.

 public class SetFocusTrigger : TargetedTriggerAction { protected override void Invoke(object parameter) { if (Target == null) return; Target.Focus(); } } 

Pour que le focus soit défini sur un contrôle, vous placez une collection Triggers après votre LayoutRoot (ou tout contrôle en réalité), sélectionnez l’événement en tant que déclencheur et sélectionnez SetFocusTrigger en tant que classe à exécuter. Dans la déclaration SetFocusTrigger, vous indiquez le nom du contrôle dont vous souhaitez recevoir le focus à l’aide de la propriété TargetName.

  

c’est ce que tu veux?

     

c #:

  public void MoveFocusOnClick(object sender, RoutedEventArgs e) { Keyboard.Focus(txtName); // Or your own logic } 

C’est la même chose que la solution de Ian Oakes, mais j’ai apporté quelques modifications mineures.

  1. Le type de bouton peut être plus général, à savoir ButtonBase , pour traiter plusieurs cas, tels que ToggleButton .
  2. Le type de cible peut également être plus général, à savoir UIElement . Techniquement, cela pourrait être IInputElement , je suppose.
  3. J’ai rendu le gestionnaire d’événements statique afin qu’il ne génère pas de fermeture du runtime à chaque fois. Pour être sûr qu’il rest statique, je l’ai sorti d’un lambda.

Merci beaucoup à Ian.


 public sealed class EventFocusAttachment { [DebuggerStepThrough] public static UIElement GetTarget(ButtonBase b) { return (UIElement)b.GetValue(TargetProperty); } [DebuggerStepThrough] public static void SetTarget(ButtonBase b, UIElement target) { b.SetValue(TargetProperty, target); } public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached("Target", typeof(UIElement), typeof(EventFocusAttachment), new UIPropertyMetadata(null, TargetPropertyChanged)); public static void TargetPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs _) { ButtonBase bb; if ((bb = o as ButtonBase) != null) bb.Click += handler; } static void handler(Object o, RoutedEventArgs _) { UIElement target; if ((target = GetTarget((ButtonBase)o)) != null) target.Focus(); } }; 

L’utilisation est fondamentalement la même que ci-dessus:

  

Notez que l’événement peut cibler / focaliser le bouton d’origine lui-même.

Regardez si vous utilisez un Dispatcher, ce serait utile, mais c’est une astuce que j’ai utilisée dans mon code. Utilisez simplement l’événement Loaded dans votre XAML et créez un nouveau gestionnaire. Dans ce gestionnaire, collez ce code et le bingo! tu es prêt à partir

Votre événement chargé avec quelques arguments ici …

 { Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, new System.Action(() => { The element to be focused goes here...... })); } 

PS: Il nécessite Windows. Enfiler si vous ne saviez pas;)