Schaltfläche "Aktivieren" basierend auf dem TextBox-Wert (WPF)

8

Dies ist MVVM-Anwendung. Es gibt ein Fenster und eine zugehörige Ansichtsmodellklasse.

Es gibt TextBox , Button und ListBox auf dem Formular. Button ist an DelegateCommand gebunden, das CanExecute function hat. Idee ist, dass der Benutzer einige Daten in das Textfeld eingibt, die Taste drückt und die Daten an das Listenfeld angehängt werden.

Ich möchte den Befehl (und die Schaltfläche) aktivieren, wenn der Benutzer korrekte Daten in TextBox eingibt. Die Dinge funktionieren jetzt so:

  • Die Methode CanExecute() enthält Code, der überprüft, ob Daten in der an das Textfeld gebundenen Eigenschaft korrekt sind.
  • Das Textfeld ist im Ansichtsmodell
  • an die Eigenschaft gebunden
  • UpdateSourceTrigger wird auf PropertyChanged gesetzt und die Eigenschaft im Ansichtsmodell wird aktualisiert, nachdem jeder Schlüsselbenutzer gedrückt hat.

Problem ist, dass CanExecute() nicht ausgelöst wird, wenn Benutzer Daten in ein Textfeld eingibt. Es wird nicht ausgelöst, selbst wenn die Textbox den Fokus verliert.

Wie könnte ich das schaffen?

Bearbeiten:
Re Yankos Kommentar:
Der Delegate-Befehl ist in der MVVM-Toolkit-Vorlage implementiert. Wenn Sie ein neues MVVM-Projekt erstellen, befindet sich der Delegate-Befehl in der Lösung. So viel wie ich in Prism-Videos gesehen habe, sollte dies die gleiche Klasse (oder zumindest sehr ähnlich) sein.

Hier ist XAML-Ausschnitt:

%Vor%

Modell anzeigen:

%Vor%

Wie ich im ersten Teil der Frage schrieb, funktionieren folgende Dinge:

  • Property Setter für ObjectName wird bei jedem Tastendruck in der Textbox
  • ausgelöst
  • Wenn ich return true; in CanAddObject() einstelle, ist der Befehl aktiv (Schaltfläche zu)

Es scheint mir, dass die Bindung korrekt ist.

Was ich nicht weiß ist, wie CanExecute() fire im Set von ObjectName property vom obigen Code gemacht wird.

Antworten von Re Ben und Abe:

  • CanExecuteChanged() ist Event-Handler und Compiler beschwert sich:

      

    Die Veranstaltung   'System.Windows.Input.ICommand.CanExecuteChanged'   kann nur auf der linken Seite erscheinen   von + = oder - =

  • Es gibt nur zwei weitere Mitglieder von ICommand : Execute() und CanExecute()

Haben Sie ein Beispiel, das zeigt, wie ich den Befehlsaufruf CanExecute() machen kann.

Ich habe in DelegateCommand.cs die Kommandomanager-Hilfsklasse gefunden und werde mich darum kümmern, vielleicht gibt es einen Mechanismus, der helfen könnte.

Wie auch immer, die Idee, dass, um den Befehl basierend auf Benutzereingaben zu aktivieren, man das Objektobjekt "anstupsen" im Eigenschaftseinstellungs-Code anstupsen muss, ist unbeholfen. Es wird Abhängigkeiten einführen und einer der großen Punkte von MVVM ist es, sie zu reduzieren.

Bearbeiten 2:

Ich habe versucht, CanExecute zu aktivieren, indem ich addObjectCommand.RaiseCanExecuteChanged() auf ObjectName property setter vom obigen Code aufruft. Dies hilft auch nicht. CanExecute() wird einige Male ausgelöst, wenn das Formular initialisiert wird, danach wird es jedoch nie erneut ausgeführt. Dies ist der Code:

%Vor%

Bearbeiten 3: Lösung

Als Yanko Yankov und JerKimball schrieb, Problem ist statische Ressource. Als ich die Tastenbindung änderte, schlug Yanko vor:

%Vor%

Dinge begannen sofort zu arbeiten. Ich brauche nicht einmal RaiseCanExecuteChanged() . Jetzt wird CanExecute automatisch ausgelöst.

Warum habe ich statische Ressource an erster Stelle verwendet?
Ursprünglicher Code war von WPF MVVM Toolkit Handbuch. Beispiel in diesem Handbuch definiert Befehle als statische Ressource und bindet sie dann an Menüelement. Der Unterschied besteht darin, dass das MVVM-Handbuch in meinem Beispiel statt der Zeichenfolgeeigenschaft mit ObservableCollection arbeitet.

Bearbeiten Sie 4: Abschließende Erklärung

Ich habe es endlich verstanden. Alles, was ich tun musste, war, Kommentare in CommandReference klasse zu lesen. Es sagt:

%Vor%

Also wird CommandReference für KeyBinding verwendet, nicht für visuelle Elemente. In obigem Code würden Befehlsverweise, die in Ressourcen definiert sind, für KeyBinding funktionieren, das ich nicht für dieses Benutzersteuerelement habe.
Natürlich war der Beispielcode, der mit WPF MVVM Toolkit geliefert wurde, korrekt, aber ich habe ihn falsch gelesen und CommandReference in den visuellen Elementen verwendet, die binden.
Diese WPF MVVM ist wirklich manchmal schwierig.

    
zendar 23.05.2017, 12:01
quelle

4 Antworten

4

Die Dinge sehen nun viel besser aus mit den Änderungen, danke! Dies könnte eine dumme Frage sein (ich bin etwas müde von der Arbeit eines langen Tages), aber warum binden Sie nicht direkt an den Befehl, statt über eine statische Ressource?

%Vor%     
irobot 12.03.2010, 18:26
quelle
3

Da Sie den DelegateCommand verwenden, können Sie die RaiseCanExecuteChanged-Methode aufrufen, wenn sich die Texteigenschaft ändert. Ich bin mir nicht sicher, was Sie mit Ihrer CommandReference-Ressource erreichen wollen, aber normalerweise binden Sie die Befehle einfach direkt an die Command-Eigenschaft des Schaltflächenelements:

%Vor%

Dies wäre der relevante Teil Ihres Ansichtsmodells:

%Vor%     
Abe Heidebrecht 11.03.2010 21:31
quelle
1

Versuchen Sie, CanExecuteChanged zu erhöhen, wenn sich Ihre Eigenschaft ändert. Die Befehlsbindung unterscheidet sich deutlich von der Eigenschaftsbindung, und Schaltflächen, die an Befehle gebunden sind, werden durch das CanExecuteChanged -Ereignis auf eine Statusänderung hingewiesen.

In Ihrem Fall könnten Sie eine Überprüfung auslösen, wenn Sie die PropertyChanged für die gebundene Eigenschaft ausführen, die sie auswerten würde, und das interne CanExecute -Flag des Befehls setzen und dann CanExecuteChanged erhöhen. Mehr von einem "Push" in das ICommand -Objekt als ein "Pull".

    
Ben Von Handorf 11.03.2010 20:17
quelle
1

Abe hier abhören, aber der "richtige" Pfad, den du hier nehmen willst, benutzt:

%Vor%

wird auf DelegateCommand angezeigt. Soweit Abhängigkeiten bestehen, glaube ich nicht, dass Sie wirklich etwas "Schlechtes" tun, indem Sie dies erhöhen, wenn die Eigenschaft, dass der Befehl von Änderungen innerhalb des ViewModels abhängt. In diesem Fall ist die Kopplung mehr oder weniger vollständig innerhalb des ViewModels enthalten.

Wenn Sie also Ihr Beispiel nehmen, würden Sie in Ihrem Setter für "ObjectName" RaiseCanExecuteChanged mit dem Befehl "AddObjectCommand" aufrufen.

    
JerKimball 12.03.2010 17:48
quelle

Tags und Links