2017-02-08 2 views
1

In der Anwendung mit einem MVVM-Ansatz ist es üblich, dass das ViewModel einen oder mehrere Command -Eigenschaften bereitstellt. Diese Eigenschaften haben oft den Typ ICommand oder DelegateCommand oder so ähnlich.Was ist der Grund für ICommand in Mvvm?

Ich verstehe nicht, warum wir einen solchen Ansatz in einer MVVM-Anwendung benötigen. Wäre es nicht genug, öffentliche Methoden bereitzustellen und die Aktion direkt von dieser öffentlichen Methode zu binden?

Warum existiert ICommand?

+3

* "Binden Sie die Aktion aus der Ansicht direkt an diese öffentliche Methode" * - das ist es, was 'ICommand' genauso gut tut wie die Ansicht, wann immer Befehl ** ausgeführt werden kann. Werfen Sie einen Blick auf ['DelegateCommand'] (https://wpftutorial.net/DelegateCommand.html) es macht es einfach. – Sinatr

+1

Einige MVVM-Frameworks wie Caliburn.Micro verwenden Namenskonventionen zum Binden von Methoden zum Anzeigen von Elementen * ohne * einen ICommand. –

+0

Man kann relativ einfach eigene Funktionen hinzufügen mit * angehängtem Verhalten * (reines MVVM): Sie können bestimmte View-Ereignisse abonnieren (Sie können dies im Code-hinter sehen, aber das wäre schmutzig MVVM), um bestimmte Methoden von ViewModel aufzurufen (direkt, über Schnittstelle oder durch Reflexion). 'ICommand' war ein absolutes Minimum, was WPF benötigt, nämlich löst es Probleme, wenn Menüpunkte/Schaltflächen deaktiviert werden, z. für das Szenario 'Kopieren' /' Einfügen'. Nichts mehr. In der Tat kann 'ButtonBase.Command' ein einfacher' Click'-Event-Handler sein, Sie können die ViewModel-Methode dort sofort aufrufen. – Sinatr

Antwort

2

Wäre es nicht ausreichend, öffentliche Methoden bereitzustellen und die Aktion aus der Sicht direkt an diese öffentliche Methode zu binden? Warum existiert ICommand?

  1. Sie können nicht auf ein Verfahren in XAML binden. Du brauchst ein Objekt. Daher müssen Sie die Methode in ein Objekt einbinden.

  2. Es ist ein häufiges Muster in der Benutzeroberfläche, dass einige Aktionen nicht immer verfügbar sind. Im Anmeldeformular wird die Login-Aktion nur verfügbar, wenn Sie den Benutzernamen eingeben. In MS Word sind die Aktionen zum Kopieren oder Ausschneiden nur verfügbar, wenn Sie etwas auswählen. Andernfalls sind die Schaltflächen deaktiviert und die Tastaturkürzel sind inaktiv.

  3. Es handelt sich um ein allgemeines Muster. Dieser Befehl kann mit anderen Parametern aufgerufen werden.

Plain Eventhandler nicht diesen Anforderungen gerecht zu werden, aber ICommand Server genau diese Zwecke:

public interface ICommand 
{ 
    void Execute(object parameter); 
    bool CanExecute(object parameter); 
    event EventHandler CanExecuteChanged; 
} 
  1. Es wickelt Methode auf ein Objekt
  2. Er sagt, ob verfügbar zu befehlen oder nein ist, so Die UI-Komponente (in der Regel eine Schaltfläche oder ein Menüeintrag) kann dies widerspiegeln.
  3. Außerdem werden die UI-Komponenten benachrichtigt, dass sich die Verfügbarkeit des Befehls geändert hat, sodass die Benutzeroberfläche reflnken kann ect es. Jetzt

, lassen Sie uns Copy & Paste Szenario in Betracht ziehen. Mit ICommand das Markup kann wie folgt aussehen:

<Button Content="Paste" Command="{Binding PasteCommand}" /> 
<MenuItem Header="Paste" Command="{Binding PasteCommand}" /> 
public ICommand PasteCommand {get;} = new DelegateCommand(Paste,() => Clipboard != null); 

Wie es wie ohne ICommand aussehen würde? Um es einfacher zu machen, kann erwägen, dass XAML erlauben würde, Methoden zu binden:

<Button Content="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}" /> 
<MenuItem Header="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}"/> 

public void Paste() {....} 

private bool _canPaste; 
public bool CanPaste 
{ 
    get { return _canPaste } 
    set 
    { 
     if (_canPaste != value) 
     { 
      _canPaste = value; 
      OnNotifyPropertyChanged(nameof(CanPaste); 
     } 
    } 
} 

wie Sie sehen können, ist es nicht nur ausführliches, aber es ist auch Verletzung von DRY-Prinzip. Sie müssen sowohl Paste als auch CanPaste Bindung jedes Mal angeben, wenn Sie den Befehl verwenden möchten. Was wäre, wenn Sie ohne CanPaste gestartet wären und später hinzufügen wollten? Dann müssten Sie die CanPaste-Bindung bei jedem Aufruf des Aufrufs Paste hinzufügen. Ich garantiere dir, dass du es irgendwo vergessen würdest.

Nun, wenn Sie dies in WPF tat

<Button Content="Paste" Click="Call_ViewModel_Paste" /> 
//in codebehind: 
void Call_ViewModel_Paste(oobject sender, RoutedEventArgs e) 
{ 
    ViewModel.Call_ViewModel_Paste(); 
} 

oder schließlich:

<Button Content="Paste"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Click"> 
      <ei:CallMethodAction MethodName="Paste" TargetObject="{Binding}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Button> 

Beide Ansätze richtig sind, folgen sie MVVM priciples und arbeitet ohne ICommand, aber Wie Sie sehen können, ist keiner so elegant wie ICommand

2

Wäre es nicht ausreichend, öffentliche Methoden bereitzustellen und die Aktion aus der Sicht direkt an diese öffentliche Methode zu binden?

Wie würden Sie zum Beispiel eine öffentliche Methode aufrufen, wenn ein Button in der Ansicht angeklickt wird?

Die Antwort ist, dass Sie die Command Eigenschaft des Button zu einer ICommand Eigenschaft des View-Modell binden, die das Verfahren für Sie anruft. Dies ist der Hauptgrund, warum alle Aktionen, die Modelldefinitionen anzeigen, mithilfe von Befehlen verfügbar gemacht werden.

Ein Befehl ist nichts anderes als ein Objekt, das die Schnittstelle System.Windows.Input.ICommand implementiert und den Code für die durchzuführende Aktion einkapselt.

Bitte beachten Sie die folgenden Links für weitere Informationen über das Konzept.

https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/ https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

+0

* »Ein Befehl ist nichts anderes als ein Objekt, das ... den Code für die durchzuführende Aktion einkapselt.« * - Aber genau das ist es * nicht, oder? Ein Befehl ist nur eine Art Markierung, die eigentliche Aktion kommt von einem Befehl * binding *. – Joey

+0

Sie verwenden keine System.Windows.Input.CommandBinding in MVVM.Sie binden an eine Eigenschaft des Ansichtsmodells, die ein ICommand-Objekt zurückgibt, und dann wird die Execute-Methode dieses ICommand-Objekts aufgerufen, wenn Sie beispielsweise auf eine Schaltfläche in der Ansicht klicken. – mm8

+0

Wie lautet die Antwort * warum * WPF-Befehle funktionieren so wie sie? Es sieht so aus, als ob das OP fragt, warum wir '{Binding MethodName}' statt '{Binding CommandObject}' nicht schreiben können. –

1

In MVVM versuchen Sie "Code hinter" (dies ist der Code in der MyView.cs-Datei) zu vermeiden, dass eine enge Kopplung von Ansicht, Ansichtsmodell und Modell zu vermeiden.

In MFC haben Sie gerade einen Event-Handler registriert (was in WPF immer noch möglich ist), aber in MVVM besteht die Möglichkeit, nur einen ICommand zu binden, der ausgeführt wird, anstatt das Event auszulösen.

+2

können Sie View an eine Methode in ViewModel binden. Tatsächlich können Sie es mit 'CallMethodAction' in xaml machen. Also das ist nicht wirklich eine Antwort warum brauchen wir ICommand – Liero

+0

Aber ein Befehl ist viel flexibler, denn es ist eine ganze Klasse, die angepasst werden kann. Z.B. Andere Eigenschaften usw. verwenden – Traummaennlein

Verwandte Themen