2010-08-05 3 views
48

Je souhaite exécuter une commande dans mon modèle de vue lorsque l'utilisateur appuie sur la touche Entrée dans un TextBox. La commande fonctionne lorsqu'elle est liée à un bouton.Exécution de la commande viewmodels à l'entrée de TextBox

<Button Content="Add" Command="{Binding Path=AddCommand}" /> 

Mais je ne peux pas le faire fonctionner à partir du TextBox. J'ai essayé une liaison d'entrée, mais cela n'a pas fonctionné. J'ai également essayé de régler le bouton de travail par défaut, mais il ne s'exécute pas lorsque vous appuyez sur Entrée.

Merci pour votre aide.

+1

Voulez-vous s'il vous plaît changer la réponse acceptée? Je ne peux pas supprimer le mien pendant qu'il est accepté. – Jay

Répondre

0

Cela fait des années que j'essaye d'enlever ceci, mais une réponse acceptée ne peut pas être supprimée. Voir https://stackoverflow.com/a/21110210/114994.

+5

Si nous avons besoin d'écrire du code dans le code-behind pourquoi ne pas appeler directement la commande dans l'événement KeyDown? – thewpfguy

+1

Parce qu'avec cette approche, vous pouvez toujours lier à votre ViewModel – Wouter

+4

Ceci est un bon exemple de la façon d'étendre les fonctionnalités quand il n'est pas disponible via XAML, et cela fonctionne. Mais la réponse correcte à cette question est celle que @mkamioner a fournie. –

5

Voici une propriété de dépendance attachée que j'ai créée pour cela. Il a l'avantage de s'assurer que votre liaison de texte est mise à jour vers ViewModel avant que la commande ne se déclenche (utile pour Silverlight qui ne prend pas en charge le déclencheur de source de mise à jour modifié par la propriété).

public static class EnterKeyHelpers 
{ 
    public static ICommand GetEnterKeyCommand(DependencyObject target) 
    { 
     return (ICommand)target.GetValue(EnterKeyCommandProperty); 
    } 

    public static void SetEnterKeyCommand(DependencyObject target, ICommand value) 
    { 
     target.SetValue(EnterKeyCommandProperty, value); 
    } 

    public static readonly DependencyProperty EnterKeyCommandProperty = 
     DependencyProperty.RegisterAttached(
      "EnterKeyCommand", 
      typeof(ICommand), 
      typeof(EnterKeyHelpers), 
      new PropertyMetadata(null, OnEnterKeyCommandChanged)); 

    static void OnEnterKeyCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
    { 
     ICommand command = (ICommand)e.NewValue; 
     FrameworkElement fe = (FrameworkElement)target; 
     Control control = (Control)target; 
     control.KeyDown += (s, args) => 
     { 
      if (args.Key == Key.Enter) 
      { 
       // make sure the textbox binding updates its source first 
       BindingExpression b = control.GetBindingExpression(TextBox.TextProperty); 
       if (b != null) 
       { 
        b.UpdateSource(); 
       } 
       command.Execute(null); 
      } 
     }; 
    } 
} 

Vous l'utiliser comme ceci:

<TextBox 
    Text="{Binding Answer, Mode=TwoWay}" 
    my:EnterKeyHelpers.EnterKeyCommand="{Binding SubmitAnswerCommand}"/> 
13

Vous avez probablement pas fait la commande d'une propriété, mais un champ. Cela fonctionne seulement pour lier aux propriétés. Changez votre AddCommand à une propriété et cela fonctionnera. (Votre XAML fonctionne bien pour moi avec une propriété au lieu d'un champ pour la commande -> pas besoin de code derrière!)

+2

D'accord. '' a bien fonctionné pour moi aussi! –

123

Je sais que je suis en retard à la fête, mais j'ai eu ça pour travailler pour moi. Essayez d'utiliser Key="Return" au lieu de Key="Enter"

Voici l'exemple complet

<TextBox Text="{Binding FieldThatIAmBindingToo, UpdateSourceTrigger=PropertyChanged}"> 
    <TextBox.InputBindings> 
     <KeyBinding Command="{Binding AddCommand}" Key="Return" /> 
    </TextBox.InputBindings> 
</TextBox> 

Assurez-vous d'utiliser UpdateSourceTrigger=PropertyChanged dans votre reliure, sinon la propriété ne sera pas mis à jour avant mise au point est perdu, et en appuyant sur Entrée ne perdre le focus ...

Espérons que cela a été utile!

+22

Il doit être accepté comme solution au lieu de la réponse acceptée avec terrible «RegisterAttached» – monstr

2

Vous devez définir Gesture au lieu de la propriété clé du KeyBinding:

<TextBox.InputBindings> 
    <KeyBinding Gesture="Enter" Command="{Binding AddCommand}"/> 
</TextBox.InputBindings> 
0

En plus de la réponse de » Mark Heath, je pris la classe un peu plus loin en mettant en œuvre de commande propriété des paramètres ci-joint de cette manière;

public static class EnterKeyHelpers 
{ 
     public static ICommand GetEnterKeyCommand(DependencyObject target) 
     { 
      return (ICommand)target.GetValue(EnterKeyCommandProperty); 
     } 

     public static void SetEnterKeyCommand(DependencyObject target, ICommand value) 
     { 
      target.SetValue(EnterKeyCommandProperty, value); 
     } 

     public static readonly DependencyProperty EnterKeyCommandProperty = 
      DependencyProperty.RegisterAttached(
       "EnterKeyCommand", 
       typeof(ICommand), 
       typeof(EnterKeyHelpers), 
       new PropertyMetadata(null, OnEnterKeyCommandChanged)); 


     public static object GetEnterKeyCommandParam(DependencyObject target) 
     { 
      return (object)target.GetValue(EnterKeyCommandParamProperty); 
     } 

     public static void SetEnterKeyCommandParam(DependencyObject target, object value) 
     { 
      target.SetValue(EnterKeyCommandParamProperty, value); 
     } 

     public static readonly DependencyProperty EnterKeyCommandParamProperty = 
      DependencyProperty.RegisterAttached(
       "EnterKeyCommandParam", 
       typeof(object), 
       typeof(EnterKeyHelpers), 
       new PropertyMetadata(null)); 

     static void OnEnterKeyCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
     { 
      ICommand command = (ICommand)e.NewValue; 
      Control control = (Control)target; 
      control.KeyDown += (s, args) => 
      { 
       if (args.Key == Key.Enter) 
       { 
        // make sure the textbox binding updates its source first 
        BindingExpression b = control.GetBindingExpression(TextBox.TextProperty); 
        if (b != null) 
        { 
         b.UpdateSource(); 
        } 
        object commandParameter = GetEnterKeyCommandParam(target); 
        command.Execute(commandParameter); 
       } 
      }; 
     } 
    } 

Utilisation:

<TextBox Text="{Binding Answer, Mode=TwoWay}" 
    my:EnterKeyHelpers.EnterKeyCommand="{Binding SubmitAnswerCommand}" 
    my:EnterKeyHelpers.EnterKeyCommandParam="your parameter"/> 
Questions connexes