Ist der Zugriff auf das ViewModel in der CodeBehind-immer gegen das MVVM-pattern?
Einer Sache bin ich mir wirklich nicht sicher ist, wie Sie richtig zu pass-Maus-events an das ViewModel. Es ist die Art und Weise der Bindung löst mit der Interaktivität Dateiendung wie zum Beispiel in: WPF-Veranstaltung verbindlich die Sicht und ViewModel?
Aber dies hat uns nicht die MouseEventArgs-meines Wissens, und diese Lösung erscheint nicht sehr elegant zu mir.
Was wäre also die richtige Lösung? Eine Möglichkeit ist das registrieren eines Ereignisses und verarbeiten es in der code-behind, z.B.:
private void ListBox_PreviewMouseDown(object sender, System.Windows.Input.MouseEventArgs e)
{
var listbox = sender as ListBox;
if (listbox == null)
return;
var vm = listbox.DataContext as MainViewModel;
if (vm == null)
return;
//access the source of the listbox in viewmodel
double x = e.GetPosition(listbox).X;
double y = e.GetPosition(listbox).Y;
vm.Nodes.Add(new Node(x, y));
}
Hier nehme ich an, dass die listbox die ItemsSource gebunden ist an die vm.Nodes-Eigenschaft. Also nochmal die Frage: ist es der richtige Weg, es zu tun? Oder gibt es einen besseren?
- Wie willst du das lösen ähnliche Aufgaben mit Daten Vorlagen?
- Dies funktioniert, indem Sie mit EventSetters wie in stackoverflow.com/questions/1800595/... ich habe es gerade ausprobiert, und es scheint zu funktionieren.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, dein Ansatz ist gut. Diese Ereignisse, dass die Arbeit mit
View
werden, können in die code-behind-wenn Sie Handler arbeiten überViewModel
. Es gibt jedoch eine alternative NutzungGalaSoft.MvvmLight
(link zum download), in denenEventToCommand
unterstützt parameterPassEventArgsToCommand
.Beispiel für die Verwendung:
Ich denke, Sie können beide Ansätze. Ihre Lösung ist einfach, erfordert nicht die Verwendung der frameworks, sondern verwendet code-hinter, in diesem Fall ist es nicht kritisch. Eine Sache ist sicher, ist es ratsam, nicht zu halten
ViewModel
event-Handler, verwenden Sie den Befehl oder speichern Sie diese Handler aufView
Seite.Some new notes
Denke ich, den Weg nicht gegen die Prinzipien der
MVVM
alle event-Handler Arbeit mitView
, sollte auf der Seite derView
, die Hauptsache - es ist der event-Handler müssen für die Arbeit mit einerViewModel
und eine Abhängigkeit über eine Schnittstelle, aber nicht direkt mit der UI.Nur Prinzip
MVVM
zu brechen - ist das mantra, "kein code" und dies ist nicht der wichtigste Grundsatz derMVVM
. Die wichtigsten Grundsätze:Split-Daten
Model
vonView
Anwendungslogik sollte nicht gebunden werden, um UI -
Unterstützung der Testbarkeit von code
Sobald der code-behind-gegen mindestens eines dieser Prinzipien ist, müssen Sie schon sehen, wie die alternativen zur Lösung Ihres Problems.
Können, können Sie auch Lesen Sie die Meinungen darüber auf diesem link:
WPF-MVVM-Code Hinter
ViewModel
, weilViewModel
soll nicht explizit wissen überView
. So, vor kurzem habe ich versucht zu bewegen, um Befehl und um zu vermeiden das Ereignis.View
sollten Sie nicht wissen, dieViewModel
. Aber was ist eigentlich mit Muster-Verletzung: ist meine Lösung die richtige ist, also akzeptiert das Muster, oder ist es nur ein akzeptabel workaround, aber gegen MVVM in der Tat?Gutes timing, ich schrieb einige code zu tun, genau dies über zwei Stunden. Sie können in der Tat Argumente, und ich persönlich thnk es ist elegant, weil es erlaubt Ihnen, in vollem Umfang testen Sie Ihre Benutzer-interface. MVVM-Lite ermöglicht es Ihnen, zu binden, Veranstaltungen zu Befehlen, die mit EventToCommand, so starten Sie, indem Sie die entsprechenden namespaces zu Ihrem control/Fenster:
Nun fügen Sie Ereignis-Trigger auf die untergeordnete Steuerelement, dessen Ereignisse, die Sie abfangen möchten:
In meinem speziellen Fall, ich bin rendering eine Sammlung von Elementen auf eine Leinwand, daher meine Verwendung des ItemsControl, aber es funktioniert auf alles, einschließlich das übergeordnete Fenster. Es funktioniert auch für Tastendrücke (z.B. KeyDown -) aber wenn Ihr Kind die Kontrolle nicht konzentrieren können, dann müssen Sie den Auslöser, um die Eltern statt. In jedem Fall bleibt, ist das hinzufügen der entsprechenden Handler an das view-model:
Eine Letzte Sache, die ich erwähnen möchte, ist, dass nur ein wenig off-topic ist oft, dass Sie brauchen, um wieder zu kommunizieren, um die code-behind-z.B. wenn der Benutzer drückt die linke Maus-Taste, müssen Sie möglicherweise fangen die Maus, aber dies kann leicht erreicht werden mit angebrachten Verhaltensweisen. Die Maus capture Verhalten ist einfach genug, fügen Sie einfach ein "MouseCaptured" boolean-Eigenschaft, um Ihre view-Modell, binden Sie Ihre angehängten Verhalten und haben es geändert-handler entsprechend reagieren. Für etwas mehr kompliziert, möchten Sie vielleicht, um ein Ereignis zu erstellen, innen Ihre view-Modell, das Ihre angeschlossenen Verhalten kann man dann abonnieren. So oder so, die UI ist nun vollständig unit-testbar und Ihre code-behind-wurde verschoben in generische Verhaltensweisen, die für die Weiterverwendung in anderen Klassen.