Gibt es eine Möglichkeit, eine Bindung vor oder beim Auslösen eines Befehls zu aktualisieren? Ich habe einige Textfelder, die ich bearbeiten und mit einem Befehl speichern kann, der über eine Tastenkombination erreichbar ist. Da die Bindung normalerweise nur aktualisiert wird, wenn das Textfeld den Fokus verliert, wird die letzte Änderung nicht beibehalten, wenn die Taste zum Speichern der Daten gedrückt wird. Stattdessen muss ich zuerst das Textfeld aus dem Textfeld herausnehmen, um es zu aktualisieren und dann zu speichern.
Gibt es eine Möglichkeit, das Update auf elegante Weise zu erzwingen? Ich benutze MVVM (aber kein MVVM-Framework), daher möchte ich UI-spezifische Dinge aus dem Befehlscode heraushalten. Außerdem möchte ich die Bindung nicht wirklich ändern, um sie bei jeder Änderung zu aktualisieren. Es ist in Ordnung, sie nur zu aktualisieren, wenn der Fokus verloren geht.
Ich habe das jetzt gelöst, indem ich den Fokus explizit auf ein anderes Element setze, bevor ich nach den Werten frage. Dies führt offensichtlich dazu, dass das Element, das derzeit den Fokus hat, es verliert und die Bindung aktualisiert.
Um den Fokus zu setzen, habe ich eine angefügte Eigenschaft geschrieben, inspiriert von Antworten auf andere Fragen. Auch zusammen mit meine andere Frage habe ich dies etwas automatisiert gemacht.
Um es zu verwenden, befestige ich meine Eigenschaft im Grunde an ein Element, in diesem Fall ein Tab-Steuerelement:
%Vor% In meinem Ansichtsmodell habe ich eine einfache boolesche Eigenschaft ShouldClearFocus
, die eine Standardeigenschaft ist, die ein PropertyChangedEvent
anhebt, damit die Datenbindung funktioniert. Dann setze ich einfach ShouldClearFocus
auf true
, wenn ich den Fokus zurücksetzen möchte. Die angefügte Eigenschaft legt automatisch den Fokus fest und setzt den Eigenschaftswert erneut zurück. Auf diese Weise kann ich ShouldClearFocus
weiterhin einstellen, ohne es auf false
dazwischen setzen zu müssen.
Die angefügte Eigenschaft ist eine Standardimplementierung mit diesem Änderungshandler:
%Vor% Auf Ihrem TextBox
müssen Sie UpdateSourceTrigger
für Ihre Textbindung festlegen, die definiert, wann die Quelle mit dem Textfeldwert aktualisiert wird. Standardmäßig ist es LostFocus
für die Eigenschaft Text
, was genau passiert - es aktualisiert nur die Quelle, wenn sie den Fokus verliert. Sie sollten den Wert von UpdateSourceTrigger
auf PropertyChanged
setzen und es wird jedes Mal aktualisiert, wenn sich der Textfeldwert ändert.
z.B.
%Vor% Path ist die Standardeigenschaft, wenn Sie den Binding-Befehl verwenden, also ist der obige Wert gleich Path=Foo
Hier ist die Klasse, die ich für eine ähnliche Situation benutzt habe:
%Vor%XAML:
%Vor% Der Aufruf von OnPropertyChanged("YourPropertyName")
wird die Ansicht veranlassen, den gebundenen Wert zu aktualisieren.
Andernfalls lesen Sie sich diese Antwort aus: WPF TextBox DataBind auf EnterKey drücken .
Ich denke, der beste Weg, dies zu tun, ist, die UpdateSourceTrigger=PropertyChanged
der Bindung zu setzen und dann Reactive Extensions
, um den Ereignisstrom zu drosseln. Auf diese Weise wird die Eigenschaft nur aktualisiert, nachdem der Benutzer für eine bestimmte Zeit aufgehört hat zu tippen (1/2 Sekunde ist ein guter Wert).
Das ist großartig, weil die Eigenschaft nicht ständig aktualisiert wird, sondern auch aktualisiert wird, ohne dass der Fokus geändert werden muss. Genau was du willst.
Hier sind einige wirklich nützliche Informationen zu Rx
Es gibt eine MVVM-Erweiterungsbibliothek, in der bindbare IObservables vorhanden sind. Das Beispiel, das sie hier haben, macht genau das, was ich vorgeschlagen habe.
Sie haben nach Eleganz gefragt: hier ist es. Und es ist auch nicht so viel Arbeit.