2010-08-05 1 views
48

Ich möchte einen Befehl in meinem Ansichtsmodell ausführen, wenn der Benutzer die Eingabetaste in eine TextBox drückt. Der Befehl funktioniert, wenn er an eine Schaltfläche gebunden ist.Ausführen des Befehls viewmodels bei Eingabe in TextBox

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

Aber ich kann es nicht von der TextBox zur Arbeit bringen. Ich habe versucht, eine Eingabebindung, aber es hat nicht funktioniert.

Ich habe auch versucht, die Arbeitsschaltfläche als Standard festlegen, aber es wird nicht ausgeführt, wenn Enter gedrückt wird.

Danke für Ihre Hilfe.

+1

Würden Sie bitte die akzeptierte Antwort ändern? Ich kann meine nicht löschen, solange sie akzeptiert wird. – Jay

Antwort

0

Ich habe seit Jahren versucht, dies zu entfernen, aber eine akzeptierte Antwort kann nicht gelöscht werden. Siehe https://stackoverflow.com/a/21110210/114994.

+5

Wenn wir Code in Code-hinter schreiben müssen, warum nicht einfach den Befehl in KeyDown-Ereignis direkt aufrufen? – thewpfguy

+1

Da mit diesem Ansatz Sie immer noch an Ihr ViewModel binden können – Wouter

+4

Dies ist ein gutes Beispiel für die Funktionalität zu erweitern, wenn es nicht über XAML verfügbar ist, und es funktioniert. Aber die richtige Antwort für diese Frage ist die, die @mkamioner zur Verfügung gestellt hat. –

5

Hier ist eine angefügte Abhängigkeitseigenschaft, die ich dafür erstellt habe. Es hat den Vorteil sicherzustellen, dass Ihre Textbindung in das ViewModel zurückgeschrieben wird, bevor der Befehl ausgelöst wird (nützlich für silverlight, das den Auslöser für die Änderung der Eigenschaft der geänderten Quelle nicht unterstützt).

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); 
      } 
     }; 
    } 
} 

Sie verwenden es wie folgt aus:

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

Sie haben wahrscheinlich nicht der Befehl eine Eigenschaft gemacht, aber ein Feld. Es funktioniert nur, um an Eigenschaften zu binden. Ändern Sie Ihren AddCommand zu einer Eigenschaft und es wird funktionieren. (Ihr XAML funktioniert gut für mich mit einer Eigenschaft anstelle eines Feldes für den Befehl -> keine Notwendigkeit für Code hinter!)

+2

Einverstanden. '' hat auch bei mir super funktioniert! –

123

Ich weiß, ich bin zu spät zur Party, aber ich habe dies für mich arbeiten. statt Key="Enter"

mit Key="Return" Versuchen ist das volle Beispiel

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

Stellen Sie sicher, UpdateSourceTrigger=PropertyChanged in Ihrer Bindung, sonst wird die Eigenschaft verwendet wird nicht aktualisiert werden, bis Fokus verloren, und die Eingabetaste drückt nicht den Fokus verlieren ...

Ich hoffe, das war hilfreich!

+22

Es muss als Lösung statt angenommene Antwort mit schrecklichen 'RegisterAttached' akzeptiert werden – monstr

2

Sie müssen Geste definieren, anstatt Key-Eigenschaft des KeyBinding:

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

Neben Mark Heath ‚s Antwort, nahm ich die Klasse noch einen Schritt weiter, indem auf diese Weise Befehl Parameter angefügten Eigenschaft implementiert;

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); 
       } 
      }; 
     } 
    } 

Verbrauch:

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