2009-03-16 4 views

Antwort

22

Der Unterschied ist, dass RelayCommand Delegaten akzeptieren kann. Sie können den RelayCommand außerhalb des ViewModel definieren. Das ViewModel kann dann Delegaten zum Befehl hinzufügen, wenn es den Befehl an ein UI-Objekt wie ein Steuerelement anlegt und bindet. Die Delegierten können wiederum auf die private Variable des ViewModels zugreifen, wie sie im Bereich des View Model selbst definiert sind.

Es wird verwendet, um die Menge des im ViewModel enthaltenen Codes zu verringern, da der Trend darin besteht, einen Routed-Befehl als verschachtelte Klasse innerhalb des ViewModel zu definieren. Die Funktionalität der beiden ist ansonsten ähnlich.

67

RoutedCommand ist Teil von WPF, während RelayCommand wurde von einem WPF Disciple, Josh Smith;).

Im Ernst, RS Conley beschrieb einige der Unterschiede. Der Hauptunterschied besteht darin, dass RoutedCommand eine ICommand-Implementierung ist, die ein RoutedEvent verwendet, um durch die Struktur zu routen, bis eine CommandBinding für den Befehl gefunden wird, während RelayCommand kein Routing ausführt und stattdessen einige Delegaten direkt ausführt. In einem M-V-VM-Szenario ist ein RelayCommand (DelegateCommand in Prism) wahrscheinlich die bessere Wahl.

34

Im Hinblick auf die Verwendung von RelayCommand und RoutedCommand in MVVM für mich der Hauptunterschied ist die folgende:

Lage Code

RelayCommand Sie den Befehl in jeder Klasse implementieren können (wie ICommand-Eigenschaft mit Delegaten), die dann üblicherweise mit der Steuerung verbunden sind, die den Befehl aufruft. Diese Klasse ist das ViewModel. Wenn Sie einen gerouteten Befehl verwenden, müssen Sie die Methoden implementieren, die sich auf den Befehl in dem codebehind des Steuerelements beziehen, da die Methoden von den Attributen des CommandBinding-Elements angegeben werden. Angenommen, dass strikte MVVM eine "leere" Codebehind-Datei bedeutet, gibt es keine Möglichkeit, Standard-Routing-Befehle mit MVVM zu verwenden.

Was RS Conley sagte, dass RelayCommand Sie die RelayCommand außerhalb des Ansichtsmodell zu definieren, erlaubt ist richtig, vor allem aber ermöglicht es Ihnen, es innerhalb das Ansichtsmodell zu definieren, die RoutedCommand nicht der Fall ist.

Routing

Auf der anderen Seite, RelayCommands unterstützen nicht die Baumführung durch (wie gesagt), was kein Problem ist, solange Ihre Schnittstelle auf einem einzigen Ansichtsmodell basiert. Wenn dies nicht der Fall ist, beispielsweise wenn Sie eine Objektgruppe mit eigenen viewModels haben und gleichzeitig einen Befehl des untergeordneten ViewModel für jedes Element aus dem übergeordneten Element aufrufen möchten, müssen Sie routing verwenden (siehe auch CompositeCommands). .

Alles in allem würde ich sagen, dass Standard RoutedCommands in strikter MVVM nicht verwendbar sind. RelayCommands sind perfekt für MVVM, unterstützen jedoch kein Routing, das Sie möglicherweise benötigen.

+0

Vielen Dank für die zusätzliche Tiefe in Ihrer Erklärung und den Hinweis auf CompositeCommands - das hat mir geholfen zu sehen, wo sie passen. –

13

Ich würde argumentieren, dass RoutedCommands in strengen MVVM absolut legal sind. Obwohl RelayCommands wegen ihrer Einfachheit oft vorzuziehen sind, bieten RoutedCommands manchmal organisatorische Vorteile.Beispielsweise möchten Sie möglicherweise, dass mehrere verschiedene Ansichten eine Verbindung zu einer gemeinsam genutzten ICommand-Instanz herstellen, ohne diesen Befehl direkt den zugrunde liegenden ViewModels auszusetzen.

Als Randnotiz erinnern Sie sich daran, dass strikte MVVM die Verwendung von Code-Behind nicht verbietet. Wenn das wahr wäre, dann könnten Sie niemals benutzerdefinierte Abhängigkeitseigenschaften in Ihren Ansichten definieren!

Um eine RoutedCommand innerhalb eines strikten MVVM-Framework verwenden Sie diese Schritte ausführen können:

für Ihren benutzerdefinierten Befehl
  1. Deklarieren Sie eine statische RoutedCommand Instanz. Sie können diesen Schritt überspringen, wenn Sie einen vordefinierten Befehl aus der ApplicationCommands-Klasse verwenden möchten. Zum Beispiel:

    public static class MyCommands { 
        public static RoutedCommand MyCustomCommand = new RoutedCommand(); 
    } 
    
  2. Bringen Sie die gewünschten Ansichten auf den RoutedCommand mithilfe von XAML:

    <Button Command="{x:Static local:MyCommands.MyCustomCommand}" /> 
    
  3. Einen Ihrer Ansichten, die zu einem geeigneten Viewmodel gebunden ist (dh je nachdem, was Ansichtsmodell der Befehlsfunktionalität implementiert) Bedürfnisse ein benutzerdefinierten DependencyProperty zu, die zu Ihrem Ansichtsmodell Implementierung gebunden werden:

    public partial class MainView : UserControl 
    { 
        public static readonly DependencyProperty MyCustomCommandProperty = 
         DependencyProperty.Register("MyCustomCommand", 
         typeof(ICommand), typeof(MainView), new UIPropertyMetadata(null)); 
    
        public ICommand MyCustomCommand { 
         get { return (ICommand)GetValue(MyCustomCommandProperty); } 
         set { SetValue(MyCustomCommandProperty, value); } 
        } 
    
  4. Th e gleiche Ansicht sich von Schritt zu dem RoutedCommand binden sollte 1. In der XAML: in Schritt erklärt

    <UserControl.CommandBindings> 
        <CommandBinding Command="{x:Static local:MyCommands.MyCustomCommand}" 
            CanExecute="MyCustomCommand_CanExecute" 
            Executed="MyCustomCommand_Executed" 
            /> 
    </UserControl.CommandBindings> 
    

    Im Code-Behind für Ihre Ansicht delegieren die zugehörigen Event-Handler wird nur auf die ICommand aus der Abhängigkeitseigenschaft 3 :

    private void MyCustomCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { 
        var command = this.MyCustomCommand; 
        if (command != null) { 
         e.Handled = true; 
         e.CanExecute = command.CanExecute(e.Parameter); 
        } 
    } 
    private void MyCustomCommand_Executed(object sender, ExecutedRoutedEventArgs e) { 
        var command = this.MyCustomCommand; 
        if (command != null) { 
         e.Handled = true; 
         command.Execute(e.Parameter); 
        } 
    } 
    
  5. Schließlich binden Ihre Viewmodel Befehl Implementierung der benutzerdefinierten Abhängigkeitseigenschaft in XAML (die eine ICommand sein sollte):

    <local:MainView DataContext="{Binding MainViewModel}" 
           MyCustomCommand="{Binding CustomCommand}" /> 
    

Der Vorteil dieses Ansatzes besteht darin, dass Ihr ViewModel nur eine einzige Implementierung der ICommand-Schnittstelle bereitstellen muss (und es kann sogar ein RelayCommand sein), während eine beliebige Anzahl von Views über den RoutedCommand daran angehängt werden kann direkt an dieses ViewModel gebunden.

Leider gibt es einen Nachteil darin, dass das ICommand.CanExecuteChanged-Ereignis nicht funktioniert. Wenn Ihr ViewModel möchte, dass die View die CanExecute-Eigenschaft aktualisiert, müssen Sie CommandManager.InvalidateRequerySuggested() aufrufen.