In einer WPF-Anwendung, die MVVM verwendet, habe ich eine Benutzersteuerung mit einem Listenansichtselement. Zur Laufzeit wird die Datenansicht verwendet, um die Listenansicht mit einer Sammlung von Objekten zu füllen.
Wie kann ein Doppelklickereignis korrekt an die Elemente in der Listenansicht angehängt werden, sodass beim Doppelklicken auf ein Element in der Listenansicht ein entsprechendes Ereignis im Ansichtsmodell ausgelöst wird und ein Verweis auf das angeklickte Element vorhanden ist?
Wie kann es auf saubere MVVM-Weise gemacht werden, dh ohne Code in der Ansicht?
Ich kann dies mit .NET 4.5 zum Laufen bringen. Scheint einfach und es wird kein Dritter oder Code benötigt.
quelle
InputBindings
in .NET 3.0 verfügbar und in Silverlight nicht verfügbar sind.Ich verwende gerne angehängte Befehlsverhalten und Befehle. Marlon Grech hat eine sehr gute Implementierung des Attached Command Behaviors. Mit diesen können wir dann der ItemContainerStyle- Eigenschaft von ListView einen Stil zuweisen, der den Befehl für jedes ListViewItem festlegt.
Hier legen wir den Befehl fest, der für das MouseDoubleClick-Ereignis ausgelöst werden soll, und der CommandParameter ist das Datenobjekt, auf das wir klicken. Hier gehe ich den visuellen Baum entlang, um den Befehl zu erhalten, den ich verwende, aber Sie können genauso gut anwendungsweite Befehle erstellen.
Für die Befehle können Sie entweder einen ICommand direkt implementieren oder einige der Hilfsprogramme verwenden , wie sie im MVVM Toolkit enthalten sind .
quelle
acb:
= AttachedCommandBehavior. Der Code kann im ersten Link in der Antwort gefunden werdenIch habe einen sehr einfachen und sauberen Weg gefunden, dies mit den Blend SDK Event-Triggern zu tun. Sauberes MVVM, wiederverwendbar und ohne Code-Behind.
Sie haben wahrscheinlich schon so etwas:
Fügen Sie jetzt eine ControlTemplate für das ListViewItem wie folgt hinzu, falls Sie noch keine verwenden:
Der GridViewRowPresenter ist die visuelle Wurzel aller Elemente "innerhalb", aus denen ein Listenzeilenelement besteht. Jetzt könnten wir dort einen Trigger einfügen, um nach gerouteten MouseDoubleClick-Ereignissen zu suchen und einen Befehl über InvokeCommandAction wie folgt aufzurufen:
Wenn Sie visuelle Elemente "über" dem GridRowPresenter haben (wahrscheinlich beginnend mit einem Raster), können Sie den Trigger auch dort platzieren.
Leider werden MouseDoubleClick-Ereignisse nicht aus jedem visuellen Element generiert (sie stammen aus Steuerelementen, aber nicht beispielsweise aus FrameworkElements). Eine Problemumgehung besteht darin, eine Klasse von EventTrigger abzuleiten und nach MouseButtonEventArgs mit einem ClickCount von 2 zu suchen. Dadurch werden alle Nicht-MouseButtonEvents und alle MoseButtonEvents mit einem ClickCount! = 2 effektiv herausgefiltert.
Jetzt können wir dies schreiben ('h' ist der Namespace der obigen Hilfsklasse):
quelle
Mir ist klar, dass diese Diskussion ein Jahr alt ist, aber gibt es bei .NET 4 irgendwelche Gedanken zu dieser Lösung? Ich stimme absolut zu, dass der Sinn von MVVM NICHT darin besteht, einen Code hinter der Datei zu entfernen. Ich habe auch das starke Gefühl, dass nur weil etwas kompliziert ist, es nicht besser ist. Folgendes habe ich in den Code dahinter eingefügt:
quelle
Mit der Aktionsfunktion von Caliburn können Sie Ereignisse Methoden in Ihrem ViewModel zuordnen . Angenommen, Sie haben eine
ItemActivated
Methode auf IhremViewModel
, dann würde die entsprechende XAML wie folgt aussehen:Weitere Informationen finden Sie in der Dokumentation und den Mustern von Caliburn.
quelle
Ich finde es einfacher, den Befehl zu verknüpfen, wenn die Ansicht erstellt wird:
In meinem Fall
BindAndShow
sieht das so aus (updatecontrols + avalondock):Der Ansatz sollte jedoch mit jeder Methode zum Öffnen neuer Ansichten funktionieren.
quelle
Ich habe die Lösung von Rushui mit den InuptBindings gesehen, konnte aber immer noch nicht den Bereich des ListViewItem erreichen, in dem kein Text vorhanden war - selbst nachdem der Hintergrund auf transparent gesetzt wurde. Daher habe ich ihn mithilfe verschiedener Vorlagen gelöst.
Diese Vorlage ist für den Fall vorgesehen, dass das ListViewItem ausgewählt wurde und aktiv ist:
Diese Vorlage ist für den Fall vorgesehen, dass das ListViewItem ausgewählt wurde und inaktiv ist:
Dies ist der Standardstil, der für das ListViewItem verwendet wird:
Was ich nicht mag, ist die Wiederholung des TextBlocks und seiner Textbindung. Ich weiß nicht, dass ich es umgehen kann, wenn ich das nur an einer Stelle deklariere.
Ich hoffe das hilft jemandem!
quelle
listviewitem
, ist es ihm wahrscheinlich egal, ob es bereits ausgewählt ist oder nicht. Es ist auch wichtig zu beachten, dass der Hervorhebungseffekt möglicherweise auch an denlistview
Stil angepasst werden muss . Up-Voted.Es gelingt mir, diese Funktionalität mit dem .NET 4.7-Framework mithilfe der Interaktivitätsbibliothek zu erstellen. Stellen Sie zunächst sicher, dass Sie den Namespace in der XAML-Datei deklarieren
Setzen Sie dann den Ereignisauslöser mit seiner jeweiligen InvokeCommandAction in der ListView wie unten beschrieben.
Aussicht:
Das Anpassen des obigen Codes sollte ausreichen, damit das Doppelklick-Ereignis auf Ihrem ViewModel funktioniert. Ich habe Ihnen jedoch die Klassen Model und View Model aus meinem Beispiel hinzugefügt, damit Sie die vollständige Idee haben.
Modell:
Modell anzeigen:
Falls Sie die Implementierung der DelegateCommand- Klasse benötigen .
quelle
Hier ist ein Verhalten, das sowohl bei
ListBox
als auch bei ausgeführt wirdListView
.Hier ist die Erweiterungsklasse, mit der das übergeordnete Element gefunden wird.
Verwendung:
quelle