Implémentation de MVF ICommand MVVM

Donc, dans cette implémentation MVVM particulière, j’ai besoin de plusieurs commandes. J’en ai vraiment eu assez d’implémenter les classes ICommand une par une, alors j’ai trouvé une solution, mais je ne sais pas à quel point c’est bien, donc la consortingbution de n’importe quel expert WPF sera grandement appréciée. Et si vous pouviez fournir une meilleure solution, mieux encore!

Ce que j’ai fait, c’est une seule classe ICommand et deux delegates qui prennent un object comme paramètre, un délégué est vide (pour OnExecute), l’autre bool (pour OnCanExecute). Donc, dans le constructeur de ma ICommand (qui est appelée par la classe ViewModel), j’envoie les deux méthodes et sur chaque méthode ICommand, j’appelle les méthodes des delegates.

Cela fonctionne vraiment bien, mais je ne suis pas sûr que ce soit une mauvaise façon de le faire, ou s’il existe une meilleure solution. Ci-dessous le code complet, toute consortingbution sera grandement appréciée, même négative, mais soyez constructif.

Merci!!

ViewModel:

public class TestViewModel : DependencyObject { public ICommand Command1 { get; set; } public ICommand Command2 { get; set; } public ICommand Command3 { get; set; } public TestViewModel() { this.Command1 = new TestCommand(ExecuteCommand1, CanExecuteCommand1); this.Command2 = new TestCommand(ExecuteCommand2, CanExecuteCommand2); this.Command3 = new TestCommand(ExecuteCommand3, CanExecuteCommand3); } public bool CanExecuteCommand1(object parameter) { return true; } public void ExecuteCommand1(object parameter) { MessageBox.Show("Executing command 1"); } public bool CanExecuteCommand2(object parameter) { return true; } public void ExecuteCommand2(object parameter) { MessageBox.Show("Executing command 2"); } public bool CanExecuteCommand3(object parameter) { return true; } public void ExecuteCommand3(object parameter) { MessageBox.Show("Executing command 3"); } } 

Je commande:

 public class TestCommand : ICommand { public delegate void ICommandOnExecute(object parameter); public delegate bool ICommandOnCanExecute(object parameter); private ICommandOnExecute _execute; private ICommandOnCanExecute _canExecute; public TestCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod) { _execute = onExecuteMethod; _canExecute = onCanExecuteMethod; } #region ICommand Members public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return _canExecute.Invoke(parameter); } public void Execute(object parameter) { _execute.Invoke(parameter); } #endregion } 

Ceci est presque identique à la façon dont Karl Shifflet a démontré un RelayCommand , où Execute déclenche une Action prédéterminée. Une solution haut de gamme, si vous me le demandez.

 public class RelayCommand : ICommand { private Predicate _canExecute; private Action _execute; public RelayCommand(Predicate canExecute, Action execute) { this._canExecute = canExecute; this._execute = execute; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return _canExecute(parameter); } public void Execute(object parameter) { _execute(parameter); } } 

Cela pourrait alors être utilisé comme …

 public class MyViewModel { private ICommand _doSomething; public ICommand DoSomethingCommand { get { if (_doSomething == null) { _doSomething = new RelayCommand( p => this.CanDoSomething, p => this.DoSomeImportantMethod()); } return _doSomething; } } } 

Lire la suite:
Josh Smith (introducteur de RelayCommand ): Patterns – Applications WPF avec le modèle de conception MVVM

J’ai écrit cet article sur l’interface ICommand.

L’idée – créer une commande universelle qui prend deux delegates: l’un est appelé lorsque ICommand.Execute (object param) est appelé, le second vérifie si vous pouvez exécuter la commande (ICommand.CanExecute (object param)) .

Nécessite la méthode pour changer d’événement CanExecuteChanged . Il est appelé à partir des éléments de l’interface utilisateur pour basculer la commande d’état CanExecute() .

 public class ModelCommand : ICommand { #region Constructors public ModelCommand(Action execute) : this(execute, null) { } public ModelCommand(Action execute, Predicate canExecute) { _execute = execute; _canExecute = canExecute; } #endregion #region ICommand Members public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return _canExecute != null ? _canExecute(parameter) : true; } public void Execute(object parameter) { if (_execute != null) _execute(parameter); } public void OnCanExecuteChanged() { CanExecuteChanged(this, EventArgs.Empty); } #endregion private readonly Action _execute = null; private readonly Predicate _canExecute = null; } 

Je viens de créer un petit exemple montrant comment implémenter des commandes dans un style de configuration plutôt que conventionnel. Cependant, il faut que Reflection.Emit () soit disponible. Le code de support peut sembler un peu bizarre mais une fois écrit, il peut être utilisé plusieurs fois.

Taquin:

 public class SampleViewModel: BaseViewModelStub { public ssortingng Name { get; set; } [UiCommand] public void HelloWorld() { MessageBox.Show("Hello World!"); } [UiCommand] public void Print() { MessageBox.Show(Ssortingng.Concat("Hello, ", Name, "!"), "SampleViewModel"); } public bool CanPrint() { return !Ssortingng.IsNullOrEmpty(Name); } } 

}

MISE À JOUR : il semble qu’il existe des bibliothèques comme http://www.codeproject.com/Articles/101881/Executing-Command-Logic-in-a-View-Model qui résolvent le problème du code standard ICommand.

@Carlo J’aime beaucoup votre implémentation, mais je voulais partager ma version et l’utiliser dans mon ViewModel

Première implémentation d’ICommand

 public class Command : ICommand { public delegate void ICommandOnExecute(); public delegate bool ICommandOnCanExecute(); private ICommandOnExecute _execute; private ICommandOnCanExecute _canExecute; public Command(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod = null) { _execute = onExecuteMethod; _canExecute = onCanExecuteMethod; } #region ICommand Members public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return _canExecute?.Invoke() ?? true; } public void Execute(object parameter) { _execute?.Invoke(); } #endregion } 

Notez que j’ai supprimé le paramètre de ICommandOnExecute et ICommandOnCanExecute et ajouté un null au constructeur

Puis utiliser dans le ViewModel

 public Command CommandToRun_WithCheck { get { return new Command(() => { // Code to run }, () => { // Code to check to see if we can run // Return true or false }); } } public Command CommandToRun_NoCheck { get { return new Command(() => { // Code to run }); } } 

Je trouve que cette méthode est plus propre car je n’ai pas besoin d’affecter des variables et d’instancier, tout cela étant fait en une seule fois.