Implementieren von MVVM in WPF ohne Verwendung von System.Windows.Input.ICommand

8

Ich versuche, eine WPF-Anwendung zu implementieren, die MVVM (Model-View-ViewModel) -Muster verwendet, und ich möchte den View-Teil in einer separaten Assembly (EXE) aus den Teilen Model und ViewModel (eine DLL) haben .

Der Twist besteht darin, die Model / ViewModel-Assembly von jeder WPF-Abhängigkeit freizuhalten. Der Grund dafür ist, dass ich es gerne aus ausführbaren Dateien mit verschiedenen (nicht WPF) UI-Technologien wiederverwenden möchte, zum Beispiel WinForms oder GTK # unter Mono.

Dies ist standardmäßig nicht möglich, da ViewModel einen oder mehrere ICommands verfügbar macht. Aber der ICommand-Typ ist im System.Windows.Input-Namespace definiert, der zum WPF gehört!

Gibt es also eine Möglichkeit, den WPF-Bindungsmechanismus ohne ICommand zu erfüllen?

Danke!

    
aoven 02.02.2009, 14:15
quelle

8 Antworten

7

Sie sollten in der Lage sein, einen einzelnen benutzerdefinierten WPF-Routingbefehl in Ihrer wpf-Ebene und einer einzelnen Befehlshandlerklasse zu definieren. Alle Ihre WPF-Klassen können mit entsprechenden Parametern an diesen einen Befehl gebunden werden.

Die Handler-Klasse kann den Befehl dann in Ihre eigene benutzerdefinierte Befehlsschnittstelle übersetzen, die Sie selbst in Ihrer ViewModel-Ebene definieren und die unabhängig von WPF ist.

Das einfachste Beispiel wäre ein Wrapper für einen Void-Delegaten mit einer Execute-Methode.

Alle verschiedenen GUI-Layer müssen einfach von ihren nativen Befehlstypen an einem Speicherort in Ihre benutzerdefinierten Befehlstypen übersetzt werden.

    
morechilli 02.02.2009, 14:34
quelle
4

WinForms verfügt nicht über die reichhaltige Datenbindungs- und Befehlsinfrastruktur, die für die Verwendung eines MVVM-Stilsichtmodells erforderlich ist.

Genauso wie Sie MVC-Controller einer Webanwendung nicht in einer Clientanwendung wiederverwenden können (zumindest nicht ohne Berge von Wrappern und Adaptern zu erstellen, die es am Ende schwerer machen, Code zu schreiben und zu debuggen, ohne dem Kunden einen Mehrwert zu bieten ) Sie können einen WPF MVVM in einer WinForms-Anwendung nicht wiederverwenden.

Ich habe GTK # nicht für ein echtes Projekt verwendet, daher weiß ich nicht, was es tun kann oder was nicht, aber ich vermute, MVVM ist sowieso nicht der optimale Ansatz für GTK #.

Versuchen Sie, das Verhalten der Anwendung so weit wie möglich in das Modell zu verschieben, haben Sie ein Ansichtsmodell, das nur Daten aus dem Modell freigibt, und ruft das Modell basierend auf Befehlen ohne Logik im Ansichtsmodell auf.

Dann für WinForms entfernen Sie einfach das Ansichtsmodell und rufen Sie das Modell direkt von der Benutzeroberfläche auf oder erstellen Sie eine andere Zwischenschicht, die auf WinForms eingeschränkterer Datenbindungsunterstützung basiert.

Wiederholen Sie dies für GTK # oder schreiben Sie MVC-Controller und Ansichten, um dem Modell ein Web-Front-End zu geben.

Versuchen Sie nicht, eine Technologie in ein Nutzungsmuster zu zwingen, das für einen anderen optimiert ist, schreiben Sie nicht Ihre eigene Befehlsinfrastruktur von Grund auf neu (ich habe es vorher getan, nicht meine produktivste Wahl), verwenden Sie die besten Werkzeuge für jede Technologie.

    
Nir 03.02.2009 14:52
quelle
4

Ich brauchte ein Beispiel dafür, also schrieb ich eines mit verschiedenen Techniken.

Ich hatte ein paar Designziele im Hinterkopf

1 - behalte es einfach

2 - absolut kein Code-Behind in der Ansicht (Window-Klasse)

3 - demonstrieren eine Abhängigkeit von nur der Systemreferenz in der ViewModel-Klassenbibliothek.

4 - Bewahren Sie die Geschäftslogik im ViewModel auf und leiten Sie direkt zu den entsprechenden Methoden, ohne eine Reihe von "Stub" -Methoden zu schreiben.

Hier ist der Code ...

App.xaml (no StartupUri ist die einzige Sache, die es wert ist)

%Vor%

App.xaml.cs (laden Sie die Hauptansicht hoch)

%Vor%

CommandRouter.cs (die Magie)

%Vor%

MainView.xaml (es gibt KEINE Code-Behind, buchstäblich gelöscht!)

%Vor%

MainViewModel.cs (enthält auch das eigentliche Modell, da dieses Beispiel so vereinfacht ist, bitte entschuldigen Sie das Entgleisen des MVVM-Musters.

%Vor%

Nur schnell und schmutzig und ich hoffe, es ist nützlich für jemanden. Ich sah ein paar verschiedene Ansätze durch verschiedene Google's, aber nichts war so einfach und einfach zu implementieren mit der geringsten Menge an Code, die ich wollte. Wenn es eine Möglichkeit gibt, noch weiter zu vereinfachen, lass es mich wissen, danke.

Happy Coding:)

BEARBEITEN: Um meinen eigenen Code zu vereinfachen, könnte es nützlich sein, die Adds in Einzeiler zu verwandeln.

%Vor%     
Dave Jellison 10.02.2011 14:10
quelle
2

Zeigen Sie die Befehle nicht nur den VM-Befehlen, sondern legen Sie Methoden offen. Verwenden Sie anschließend angefügte Verhaltensweisen, um Ereignisse an die Methoden zu binden. Wenn Sie einen Befehl benötigen, verwenden Sie einen ICommand, der an diese Methoden delegieren und den Befehl über angefügte Verhaltensweisen erstellen kann.

    
wekempf 27.03.2009 21:38
quelle
2

Natürlich ist das möglich. Sie können nur eine weitere Abstraktionsebene erstellen. Fügen Sie Ihre eigene IMyCommand-Schnittstelle hinzu, die der von ICommand ähnelt oder dieselbe ist, und verwenden Sie diese.

Sehen Sie sich meine aktuelle MVVM-Lösung an, die die meisten Probleme löst, die Sie erwähnt haben, aber vollständig von plattformspezifischen Dingen abstrahiert ist und wiederverwendet werden kann. Auch habe ich keine Code-Behind-Bindung mit DelegateCommands verwendet, die ICommand implementieren. Dialog ist im Grunde eine View - ein separates Steuerelement, das sein eigenes ViewModel hat und das vom ViewModel des Hauptbildschirms aus angezeigt wird, aber über die DelagateCommand-Bindung von der Benutzeroberfläche ausgelöst wird.

Siehe die vollständige Silverlight 4-Lösung hier Modale Dialoge mit MVVM und Silverlight 4

    
Roboblob 21.01.2010 21:19
quelle
2

Sorry Dave, aber deine Lösung hat mir nicht sehr gefallen. Zuerst müssen Sie die Installation für jeden Befehl manuell in Code codieren, dann müssen Sie den CommandRouter konfigurieren, um über jede Ansicht / Viewmodel-Zuordnung in der Anwendung zu erfahren.

Ich habe einen anderen Ansatz gewählt.

Ich habe eine Mvvm-Dienstprogramm-Assembly (die keine WPF-Abhängigkeiten hat) und die ich in meinem Ansichtsmodell verwende. In dieser Assembly deklariere ich eine benutzerdefinierte ICommand-Schnittstelle und eine DelegateCommand-Klasse, die diese Schnittstelle implementiert.

%Vor%

Ich habe auch eine Wpf-Bibliothek Assembly (die auf die System-WPF-Bibliotheken verweist), die ich von meinem WPF-UI-Projekt referenziere. In dieser Assembly deklariere ich eine CommandWrapper-Klasse mit der standardmäßigen System.Windows.Input.ICommand-Schnittstelle. CommandWrapper wird mit einer Instanz meines benutzerdefinierten ICommand erstellt und delegiert einfach Execute, CanExecute und CanExecuteChanged direkt an meinen benutzerdefinierten ICommand-Typ.

%Vor%

In meiner Wpf-Assembly erstelle ich auch einen ValueConverter, der, wenn er übergeben wird, eine Instanz meiner benutzerdefinierten ICommand eine Instanz des Windows.Input.ICommand kompatiblen CommandWrappers ausspuckt.

%Vor%

Jetzt können meine Ansichtsmodelle Befehle als Instanzen meines benutzerdefinierten Befehlstyps anzeigen, ohne dass eine Abhängigkeit von WPF besteht, und meine Benutzeroberfläche kann Windows.Input.ICommand-Befehle an diese Ansichtsmodelle binden, die meinen ValueConverter verwenden. (XAML-Namespace-Spam fehlt).

%Vor%

Wenn ich jetzt wirklich faul bin (was ich bin) und nicht darauf achten kann, den CommandConverter jedes Mal manuell anzuwenden, dann kann ich in meiner Wpf-Assembly meine eigene Binding-Unterklasse wie folgt erstellen:

%Vor%

So kann ich jetzt noch einfacher an meinen benutzerdefinierten Befehlstyp binden:

%Vor%     
Neutrino 05.11.2013 17:42
quelle
1

Ich denke, Sie trennen Ihr Projekt an einem falschen Punkt. Ich denke, Sie sollten nur Ihre Modell- und Geschäftslogikklassen teilen.

VM ist eine Anpassung des Modells an WPF Views. Ich würde VM einfach halten und genau das tun.

Ich kann mir nicht vorstellen, MVVM auf Winforms zu zwingen. OTOH mit nur Modell & amp; Geschäftslogik können Sie diese bei Bedarf direkt in ein Formular einfügen.

    
Kugel 06.05.2011 16:15
quelle
0

"Sie können einen WPF-MVVM in einer WinForms-Anwendung nicht wiederverwenden"

Siehe dazu Ссылка , ich habe MVVM in Win Form verwendet, jetzt, wo ich die Präsentation der Anwendung von Win aktualisieren möchte Form zu WPF wird ohne Änderung der Anwendungslogik geändert,

Aber ich habe ein Problem mit der Wiederverwendung von ViewModel in Asp.net MVC, so dass ich dieselbe Desktopanwendung im Web ohne oder mit weniger Änderungen in der Anwendungslogik machen kann.

Danke ...

    
Miraj Baldha 25.07.2011 13:08
quelle

Tags und Links