2010-06-03 6 views

Antwort

15

Dies ist eine dieser Schmerz-in-der% ¤ # Antworten, wo ich nicht wirklich Ihre Frage beantworten, sondern stattdessen Ihnen vortragen, was Sie anders machen sollten. Es tut mir Leid. Hier gehts:

Wenn Sie sich in einer Position befinden, wo Sie auf das Absenderobjekt in Ihrem Viewmodel zugreifen müssen, dann sollten Sie wahrscheinlich etwas anderes tun. Wenn Sie beispielsweise in Ihrem Ansichtsmodell auf einen Button oder eine ListBox verweisen, haben Sie dieses Viewmodel über UI-Konzepte informiert, über die es nichts wissen sollte. Mein Vorschlag ist, sich stattdessen auf der Code-Behind-Seite mit dem Ereignis zu verbinden, herauszufinden, was Sie über den Absender wissen müssen oder was nicht, und dann den Befehl viewmodel programmgesteuert auszuführen. Das bricht auch die MVVM "Regeln", aber IMHO ist es ein viel leichterer Hack, als den Absender in Ihrem Viewmodel zu referenzieren.

+0

So wie die VM nicht visibilty aussetzen (und stattdessen einen Konverter in der XAML verwenden), vielleicht sollte es eine Möglichkeit geben, einen Konverter für den Gang in die andere Richtung zu verwenden ... konvertieren von einem View basierte eventarg in einen Nicht-Sichttyp? –

+0

Wie verletzt Ihr Vorschlag auch die MVVM-Regeln? Scheint mir gut. –

+0

Ich denke, mein Hauptproblem zu der Zeit war, dass es zu kompliziert ist, verglichen mit der Bindung der Schaltfläche (in der Ansicht) an den Befehl in der VM. Wenn ich es jetzt betrachte, denke ich, dass du recht hast. Es bricht wirklich keine Regeln. –

9

Ich hatte ein ähnliches Problem, aber nur benötigt, um die EventArgs zu bekommen. Gerne war das absurd einfach, als ich die Antwort in einem anderen Thread hier bei Stack Overflow fand.

<cmd:EventToCommand Command="{Binding SomeCommand, Mode=OneWay}" PassEventArgsToCommand="True"/> 

Sobald Sie über diese Magie wissen "PassEventArgsToCommand" -Einstellung, sie ist golden. Verwenden Sie einfach einen RelayCommand<type> anstelle eines einfachen RelayCommand.

Ich hoffe, das hilft.

+5

Ich möchte nur dazu kommentieren: PassEventArgsToCommand ist nicht sehr sauber, weil es die Trennung von Bedenken unterbricht, indem eine UI-Klasse (die EventArgs) in die VM gebracht wird. Dadurch wird Ihre VM weniger testbar. Es gibt jedoch Szenarien (z. B. Drag & Drop), bei denen alles andere noch dreckiger wäre. Deshalb habe ich das EventToCommand hinzugefügt. Verwenden Sie jedoch mit viel Sorgfalt! – LBugnion

+2

Obwohl PassEventArgsToCommand möglicherweise nicht sauber ist, fand ich es nützlich, SkyDrive-Unterstützung für meine WP7-App hinzuzufügen. Der Signin-Button übergibt die Live-Session-Information über die Event-Args. Ich könnte wahrscheinlich das Ereignis in Code-Behind behandeln, setzen Sie die Session-Eigenschaft auf das ViewModel und rufen Sie dann einen Befehl auf. Der PassEventArgsToCommand hilft, verständlichen Code zu schreiben. – rams

5

Dies kann durch Bindung des Senders an den Befehlsparameter erfolgen.

<command:EventToCommand 
       Command="{Binding CommandName}" 
       CommandParameter="{Binding RelativeSource= 
             { RelativeSource FindAncestor, 
              AncestorType={x:Type TypeOfSender}, 
              AncestorLevel=1}}" 
       PassEventArgsToCommand="True" > 
</command:EventToCommand> 
+1

Ich habe dies aufgestockt, weil, während Henrik zu Recht erklärt, dass dies nicht getan werden sollte, die Welt nicht perfekt ist und das Erzielen von reinem MVVM manchmal unmöglich ist. Wenn beispielsweise ein Textfeld den gesamten Text auswählen soll, wenn es den Fokus erhält, benötigen Sie das Textfeld selbst, um das SelectAll() -Member aufzurufen. Es ist zweifellos in MVVM machbar, aber es wird wahnsinnig komplexen Code erstellen, während diese Lösung in einigen Situationen "gut genug" ist. Ich stimme zu, dass dieses Verhalten so weit wie möglich verhindert werden sollte, aber manchmal muss man nur pragmatisch sein und eine Korrektur wie diese, während hässlich, funktioniert. – Bas

+2

Ein anderes Beispiel: das WPF WebBrowser-Steuerelement. Sie können einen Befehl an das Ereignis Navigated binden, aber wenn Sie tatsächlich etwas mit der HTTP-Antwort machen möchten, benötigen Sie einen Verweis auf den Browser selbst, da diese Informationen nicht in den Ereignisvariablen enthalten sind. – Bas

Verwandte Themen