2009-05-22 4 views
0

Ich verwende das MVVM-Muster pro Josh Smith und Schwierigkeiten haben. Ich habe das Problem hier untersucht und kann die Syntax nicht ganz richtig finden.RelayCommand Lambda Syntax Problem

Der folgende Code sieht für mich aus, als ob es die erforderliche Syntax folgt, aber Visual Studio meldet Fehler "Delegate 'System.Action' nicht '2' Argumente" auf der angegebenen Zeile.

Kann jemand sehen, wo ich einen Fehler mache? Vielen Dank!
+ tom

RelayCommand _relayCommand_MoveUp; 
    public ICommand RelayCommand_MoveUp 
    { 
     get 
     { 
     if (_relayCommand_MoveUp == null) 
     { 
      _relayCommand_MoveUp = new RelayCommand(
      (sender, e) => this.Execute_MoveUp(sender, e),  **ERROR REPORTED HERE** 
      (sender, e) => this.CanExecute_MoveUp(sender, e)); 
      return _relayCommand_MoveUp; 
     } 
     } 
    } 

    private void Execute_MoveUp(object sender, ExecutedRoutedEventArgs e) 
    { 
     if (_selectedFolder != null) 
     { 
     _selectedFolder.SelectParent(); 
     } 
    } 

    private void CanExecute_MoveUp(object sender, CanExecuteRoutedEventArgs e) 
    { 
     e.CanExecute = (_selectedFolder != null) && (_selectedFolder.Parent != null); 
     } 


//And from Josh Smith: 

    public class RelayCommand : ICommand 
    { 
    public RelayCommand(Action<object> execute); 
    public RelayCommand(Action<object> execute, Predicate<object> canExecute); 

    public event EventHandler CanExecuteChanged; 

    [DebuggerStepThrough] 
    public bool CanExecute(object parameter); 
    public void Execute(object parameter); 
    } 

Antwort

2

Die RelayCommand ist kein RoutedCommand, was ich denke, ist, wo Sie verwirrt enden.

Die Konstruktoren für den Relaisbefehl nehmen eine Action delegate und optional Predicate delegate. Diese Delegaten verwenden keine EventArgs, sondern nur den einzelnen Object-Parameter. Aus diesem Grund tritt ein Fehler auf. Das Prädikat erfordert auch einen Rückgabetyp von bool, was der nächste Fehler ist, den Sie erhalten. Im CanExecute-Vergleichselement anstelle von e.CanExecute wie bei einem RoutedCommand geben Sie einfach true/false zurück.

Hier ist, wie es aussehen sollte:

public ICommand RelayCommand_MoveUp 
{ 
    get 
    { 
    if (_relayCommand_MoveUp == null) 
    { 
     _relayCommand_MoveUp = new RelayCommand(Execute_MoveUp, CanExecute_MoveUp); 

    } 
    return _relayCommand_MoveUp; 
    } 
} 

private void Execute_MoveUp(object sender) 
{ 
    if (_selectedFolder != null) 
    { 
    _selectedFolder.SelectParent(); 
    } 
} 

private void CanExecute_MoveUp(object sender) 
{ 
    return (_selectedFolder != null) && (_selectedFolder.Parent != null); 
} 



EDIT (Hinzugefügt von Diskussion in den Kommentaren):

Wenn Sie etwas mehr wie die RoutedCommands verwenden möchten, was die machen ViewModels sind stärker abhängig von WPF-spezifischen Ansichten. Es sind einige gute Optionen verfügbar.

Diese discussion hat die ganze Idee der Verwendung von RoutedCommands in Verbindung mit MVVM gestartet.

Und here's eine sehr solide Lösung für die Probleme von Josh Smith und Bill Kempf vorgestellt.

+1

Danke, rmoore:

Um einen Parameter an den Delegaten übergeben, werden Sie seine neue RelayCommand <T> Konstruktor stattdessen verwenden müssen. Also, verstehe ich richtig, wenn ich auf die EventArgs innerhalb der aufgerufenen Methode zugreifen muss, kann ich die RelayCommand-Klasse nicht verwenden, um sie aufzurufen? + tom –

+0

Das ist korrekt, das grundlegende ICommand implementiert keine Ereignisse, in der Tat weder nach meinem Wissen der RoutedCommand, die tatsächlich kommen aus etwas, das ein CommandBinding genannt wird, wonach der RoutedCommand sucht. Ich habe einige zusätzliche Informationen für RoutedCommands in MVVM zu meinem Post hinzugefügt, da in diesem Kommentar nicht genug Platz ist =) – rmoore

+0

Vielen Dank! +10 ... –

3

An diesem Wochenende (22. August) checkte Josh Smith neue Änderungen in Codeplex für sein MvvmFoundation-Projekt ein, das die Funktionsweise von RelayCommand für Delegaten mit einem Parameter ändert. In acht nehmen!

public ICommand GotoRegionCommand 
    { 
     get 
     { 
      if (_gotoRegionCommand == null) 
       _gotoRegionCommand = new RelayCommand<String>(GotoRegionCommandWithParameter); 
      return _gotoRegionCommand; 
     } 
    } 
    private void GotoRegionCommandWithParameter(object param) 
    { 
     var str = param as string; 
    } 
+0

Danke für die Info, jasonD. Ich habe den Josh Smith Code zugunsten der neuen MS MVVM Toolkit 0.1 Visual Studio Projektvorlage aufgegeben, mit der ich * sehr * zufrieden bin. Es ist einfach zu bedienen und hat eine sehr gute Dokumentation. Siehe http://wpf.codeplex.com/Wiki/View.aspx?title=WPF%20Model-View-ViewModel%20Toolkit. –