| 

.NET C# Java Javascript Exception

4
Ich habe ein DataGrid mit einer Liste von Dateien, die zu einem bestimmten Vorgang gehören. Wenn der Benutzer nun einen Doppelklick auf die Datei macht, dann soll sich das Verknüpfte Programm öffnen.

Wie würde man es MVVM-konform implementieren? Wäre das eine Funktion, die man im Codebehind der View unterbringt oder eher in der Model-Schicht?

Vielen Dank für die Beteilung an dieser Auskunftssuche ;-)
News:
19.06.2013
MyKey0815 1,6k 2 9
3 Antworten
1
Hier unterscheiden sich die Puristen von den Pragmatikern.

Die Puristen sagen "no code-behind". Klar kann man das so mit den Interaction Triggers machen.

MVVM sagt aber eigentlich "nur", dass der View nicht mit dem Model interagieren darf, sondern nur mit dem View-Model.

Es ist völlig konform, wenn du einen Click EventHandler im XAML registrierst, im Body des Handlers dann eine Methode im View-Model aufrufst.

Commands sind überhaupt kein zwingender Teil von MVVM, manchmal sind sie allerdings sehr hilfreich - aber eben nicht immer. Kann ich gar nicht oft genug in die Welt hinaus posten ;)

Was die Frage nach dem Prozess starten angeht. Ich finde, dies kann man schon durchaus im Model kapseln, aber nur wenn das Model ausschließlich in einer Client-Anwendung benutzt wird. Was nützt den die Methode, wenn das Model, dann mal auf einem Webserver benutzt wird?

Ansonsten ist es sicher direkt im View-Model durchaus gut aufgehoben.
19.06.2013
kleffel 654 1 9
kleffel 654 1 9
Danke für die Erklärung dazu. Ich denke ich werde in diesem Sinne umsetzen. Der Click-EventHandler übergibt dann den Dateinamen und im ViewModel wird dann die Auswertung erfolgen.
Danke für die Beschreibung
MyKey0815 20.06.2013
Ich gehöre dann wohl eher zu den Puristen, denn meine Views kennen kein typisiertes ViewModel, auf dem sie irgendwelche Methoden aufrufen könnten. Bei mir kennt die View Ihren DataContext als System.Object, ich müsste also erst casten, um das typisierte ViewModel zu erhalten. Aus diesem Grund handhabe ich das ebenso wie @judgy in seiner Antwort vorschlägt.
ffordermaier 20.06.2013
Verzeih kleffel, aber Deine Antwort ist einfach falsch. Es hat nichts mit Puristen oder nicht Puristen zu tun. Commands sind (!) ein wesentlicher Bestandteil von MVVM. In dem Du das ViewModel in der Code Behind Datei der View aufrufst, verbindest Du View und ViewModel, was dem Prinzip des Separation of Concerns (SoC) widerspricht. In dem Events über EventToCommand Behaviours auf das ViewModel abgebildet werden, hat man eine klare Trennung und Ordnung von Logik und View.
Ich gebe aber zu, dass man nicht immer um die Code Behind Datei herumkommt, weil VS View zentriert aufgebaut ist.
judgy 20.06.2013
@judgy: Kannst Du mir ein Beispiel nennen, bei dem man nicht um CodeBehind rumkommt? Ich habs bisher immer irgendwie geschafft, meine Geheimwaffe sind Attached Behaviors (von denen in der Blend Library ja auch ein gutes Dutzend rumliegen).
ffordermaier 20.06.2013
@judgy dass das View mittels Command Binding nicht vom View-Model abhängt ist Haarspalterei. Ein Aufruf per Reflection ist im Endeffekt nicht anderes als Duck Typing und inhaltlich ist die Abhängigkeit eben da. Wenn du wirklich willst, dass das Codebehind keine Referenz auf das View-Model besitzt, dann benutzt eben das dynamic Keyword für den DataContext. XAML und Codebehind sind beides der View. Ob dies deklarativ im XAML oder prozedural im Codebehind geschieht, ändert nichts an den Abhängigkeiten
kleffel 20.06.2013
@ffordermaier: Bei der PasswortBox funktioniert kein DataBinding. In so einem Fall wird es schwierig, ohne CodeBehind.
Xantiva 21.06.2013
Ok. Aber da würd ich eher eine vernünftige PasswordBox implementieren oder zum Attached Behavior greifen. Der Vorteil des Behaviors ist, dass der Code wiederverwendbar ist und nicht in einer einzigen CodeBehind Datei rumliegt (und vlt. sogar in andere kopiert wird).
ffordermaier 21.06.2013
@kleffel Ich weiss nicht, ob Du es nicht vielleicht komplizierter machst als es ist. Das ViewModel ist ein Abbild der View, welches mittels loser Kopplung (Binding) mit der View verknüpft wird. Das ist das Prinzip vom MVVM. Zum ViewModel gehören Eigenschaften und Methoden. Letzteres werden über EventToCommand Behaviours auf Commands im VM abgebildet.
Die Tatsache, dass es überhaupt eine Code Behind Datei gibt, hat mit dem antiquierten view-zentrierten Ansatz von Microsoft zu tun. Dort meint man immer noch mit diesem Quick-und Dirty Ansatz mehr Leute zu erreichen. Daher Finger weg davon.
judgy 24.06.2013
@ffordermaier
Bei Windows Store/WP Apps kommt man nicht immer um die Code Behind Datei herum.
judgy 24.06.2013
@judgy: Ok, danke für Info. Damit hab ich mich noch nicht beschäftigt. Hatte die WPF Brille auf.
ffordermaier 24.06.2013
2
@judgy Falls Du eine Quelle hast, die
a) MVVM als >Pattern< beschreibt
b) erklärt, dass/warum Commands wesentl. Bestandteil des Patterns sind (nicht nur eine gängige Variante seiner Implementierung)
c) erklärt, warum ein Aufruf des VM aus dem CodeBehind eine SoC-Verletzung darstellt
wäre ich sehr an einem Link interessiert. Einer, der nur a) erfüllt, wäre aber auch schon nicht schlecht. Ich kenne da eigentlich auch nur http://martinfowler.com/eaaDev/PresentationModel.html aus der Zeit, als MVVM noch PresentionModel hieß. Die meisten MVVM-Artikel reden immer gleich über die Implementierung.
Matthias Hlawatsch 24.06.2013
1
@kleffel: Noch eine Anmerkung zum Starten des Prozesses. Ich hätte überhaupt nichts dagegen, wenn dies vom ViewModel getriggert würde, durch Aufruf irgendeiner Komponente (via Interface). Nur im ViewModel selbst sollte sich mMn kein "Process.Start(...)" o.ä. finden. Sonst erschwerst Du das Unit-Testen des VM, und das ist doch gerade einer der wesentlichen Vorteile von MVVM.
Matthias Hlawatsch 25.06.2013
@Hlawatsch: Das war einer der Haupgründe, warum ich das eigentlich gefragt habe: testen des VM. Aber hier wurden ja sehr umfangreiche Erläuterungen geschrieben, die ich jetzt für meinen Fall durchdenken werde.
MyKey0815 25.06.2013
4
Welches MVVM Framework setzte Du ein?
Über die Blend Interactivity Bibliothek kannst Du Events auf Commands abbilden und auf Dein ViewModel mappen. Je nach Framework werden die Commands angeboten.
Das sieht dann etwas so aus:
<ListBox Name="list">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<Command:EventToCommand
Command="{Binding Path=DataContext.DoSomethingCommand,ElementName=list}"
CommandParameter="{Binding EventArgs.OriginalSource.DataContext, RelativeSource={RelativeSource Self}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
19.06.2013
judgy 3,0k 1 1 8
+1, genauso mach ich das auch.
ffordermaier 20.06.2013
3
@judgy Falls Du eine Quelle hast, die
a) MVVM als >Pattern< beschreibt
b) erklärt, dass/warum Commands wesentl. Bestandteil des Patterns sind (nicht nur eine gängige Variante seiner Implementierung)
c) erklärt, warum ein Aufruf des VM aus dem CodeBehind eine SoC-Verletzung darstellt
wäre ich sehr an einem Link interessiert. Einer, der nur a) erfüllt, wäre aber auch schon nicht schlecht. Ich kenne da eigentlich auch nur http://martinfowler.com/eaaDev/PresentationModel.html aus der Zeit, als MVVM noch PresentionModel hieß. Die meisten MVVM-Artikel reden immer gleich über die Implementierung. – Matthias Hlawatsch vor 4h

@Matthias: Ich antworte hier einmal ausführlich.
Ich habe vor 3 Jahren einmal einen Vortrag zu MVVM in der Berliner UG gehalten. (Die Powerpoint Folien sollte man starten, da sie viele Animationen enthalten). Heute würde ich den Vortrag ein wenig anders aufbauen, da ich denke, dass beim MVVM Pattern ein Controler fehlt und das Pattern MVVM-C heissen müsste.

Es ist wahr, dass es keine guten Artikel zum Thema MVVM gibt.
Mittlerweile glaube ich, dass es auch daran liegt, dass dieses Pattern nicht zu Ende gedacht und daher auch nicht vernünftig definiert wurde.

Die Gretchen-Frage dieses Pattern liegt in der Frage, wo die Logik liegt, die auf das Repository bzw auf den (WCF) Service zugreift: Im Model oder im ViewModel?
Daher gibt es auch so viele unbefriedigende Erklärungen und Beispiele.
Meine Antwort hierzu: Weder noch.
Desweiteren wird leider immer wieder vermischt, wer mit wem kommuniziert. Dabei wird das Model häufig direkt über das ViewModel an die View gekoppelt.

Gehen wir logisch vor:
Unser Ausgangslage ist SoC - die Belange sollen von einander getrennt werden. Das hat zur Folge:
View <- ViewModel <-> Model

Das ViewModel ist ein Abbild der View
Und das Model wird auf das ViewModel projiziert, bzw. injiziert.
Ins ViewModel kommen dann neben den Eigenschaften des injizierten Models, noch Funktionalitäten über Commands hinzu.
Das ViewModel ist dadurch definiert, das es das Prinzip des Bindings unterstützt, also vom INotifyPropertyChanged ableitet.

Übersichtlicher wird es durch
View <- ViewModel <-> ServiceAgent/Controler <-> Model

Zur Initialisierung des ViewModels wird über den Controler das Model injiziert.
Methoden, die über Comdands aufgerufen werden, führen erneut über den Controler zur Aktualisierung des Models. Das Model könnte z.B. auch der Proxy des WCF Service sen.

Wenn aber das ViewModel das Abbild der View ist, so haben wir es nicht nur mit einem ViewModel zu tun. Wir müssen es unterscheiden:
  • PageViewModel
    Auf einer Seite sind nicht nur reine Daten abgebildet, sondern werden auch unterschiedliche Strukturen zusammengeführt. Desweiteren werden Operationen wie CRUD oder Navigation dort untergebracht. Man könnte es auch so formulieren, dass es auf einer Seite unterschiedliche Controls gibt, die je für ein DataViewModel stehen.
  • DataViewModel
    Ein DataViewModel ist ein Abbild eines Models, wie es oben beschrieben wurde.
  • ResourceViewModel
    Lokalisierte Texte werden über Ressourcen in die View eingebunden. Wenn wir unser Pattern korrekt anwenden, so müssten wir hierfür eine RessourceViewModel einführen, das je nach Sprache unsere View füllt.

Damit haben wir nun folgendes Bild
-  
<- PageViewModel
View <- DataViewModel <-> ServiceAgent/Controler <-> Model
<- RessourceViewModel


Soweit, ich bin jetzt noch nicht auf Deine Fragen eingegangen.
Warum gehören Commands in das ViewModel?
Antwort: Weil es Sinn macht! Weil es 'schön' ist.
Man kann die View jederzeit austauschen. Im Idealfall kann man eine Window Phone View gegen eine WinRT View gegen eine WPF View gegen eine Silverlight View austauschen.
Ok geht nicht, weil Micrsoft nicht so genau weiss, wohin es gehen soll.
Aber dies wäre das Ideal. Und das Ideal sollte unser Ziel sein. (Deswegen wird IMO auch WP8 bald tot sein und in WinRT überführt werden)
Und ja, man kann wie früher beim MVC Pattern auch die ViewModel in die Code Behind Datei injizieren, aber es widerstrebt mir. Man muss halt die Codebehind Datei überall mit hinschleppen.

Microsoft bleibt hier seit Jahren auf der Stelle stehen. Es wurden einst ObservableCollections eingeführt, aber das IPropertyNotifyChanged Interface mit all dem Boilerplate Code muss man immer noch mitschleppen, um das Binding zu realisieren.
Microsoft spielt nicht mit, daher wird es nie richtig funktionieren. Leider.
24.06.2013
judgy 3,0k 1 1 8
Danke für den umfangreichen Beitrag (und wenn ich noch bewerten könnte, gäbe es +1 schon allein für die Zeit, die Du Dir dafür genommen hast). Inhaltlich muß ich mir den nochmal in Ruhe ansehen. Vielleicht kannst Du noch die Semantik der Pfeile in dem ersten "Diagramm" erläutern. Vor allem der vom ViewModel zur View irritiert mich. Die üblichen Semantiken "kennt", "hängt ab von", "ruft auf" passen ja alle nicht.
Matthias Hlawatsch 25.06.2013
Ich wäre dafür, dass mal in einem neuen Thread in der Lounge aufmacht, um das Wesen von MVVM zu diskutieren. Ich finde es hat viele Vorteile, aber Design-ability und sogar (welch Ketzerei!) Test-ability ist zwar nett, aber nicht der Hauptvorteil!
kleffel 25.06.2013
@kleffel: ja, könnte interessant sein, dies einmal von allen Seiten zu betrachten. Ich gebe zu, dass man irgendwann zu viele Bäume sieht und die Alternativen übersieht.
Ich halte jedoch diese Plattform als Diskussionsplattform ungeeignet. Die Kommentarfunktion ist wirklich nur zur Kommentierung und nicht zur Diskussion und die Antwortfunktion beantwortet die Frage eines Einzelnen und unterstützt nicht die Diskussion.
Die Lounge ist mehr so ein Pseudoforum, was von den Funktionen her kein Forum ist, aber durch Andreas Fragen am Leben gehalten wird. ;-)
Das Forum fehlt...
judgy 26.06.2013

Stelle deine Mvvm-Frage jetzt!