web-dev-qa-db-fra.com

Pourquoi RelayCommand

Je programme beaucoup dans WPF dernièrement, mais mon View et ViewModel ne sont pas séparés à ce stade. Eh bien, c'est partiellement. Toutes mes liaisons concernant le texte dans les zones de texte, le contenu des étiquettes, les listes dans les grilles de données, ... sont effectuées par des propriétés standard avec un événement NotifyPropertyChanged.

Tous mes événements pour gérer les clics sur les boutons ou les modifications de texte sont effectués en liant les événements. Maintenant, je voulais commencer à travailler avec des commandes et j'ai trouvé cet article: http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute . Il explique comment configurer MVVM, mais je suis confondu avec le RelayCommand.

Quel travail fait-il? Est-il utilisable pour toutes les commandes de mon formulaire? Comment puis-je désactiver le bouton lorsque (a) certaines zones de texte ne sont pas renseignées?


EDIT 1:

Une bonne explication à "Est-il utilisable pour toutes les commandes de mon formulaire?" est répondu ici: https://stackoverflow.com/a/22286816/3357699

Voici le code que j'ai jusqu'à présent: https://stackoverflow.com/a/22289358/3357699

40
Krowi

Les commandes sont utilisées pour séparer la sémantique et l'objet qui appelle une commande de la logique qui exécute la commande c'est-à-dire qu'il sépare le composant d'interface utilisateur de la logique qui doit l'être être exécuté sur invocation de commande. Ainsi, vous pouvez tester la logique métier séparément à l'aide de scénarios de test et votre code d'interface utilisateur est faiblement couplé à la logique métier.

Maintenant, cela étant dit, sélectionnons vos questions une à une:

Quel travail fait-il?

J'ai ajouté les détails ci-dessus. J'espère que cela efface l'utilisation des commandes.


Est-il utilisable pour toutes les commandes de mon formulaire?

Certains contrôles exposés Command DependencyProperty comme Button, MenuItem, etc., qui ont un événement par défaut enregistré. Pour Button, c'est l'événement Click. Donc, si vous liez ICommand déclaré dans ViewModel avec la commande DP de Button, il sera invoqué chaque fois que vous cliquerez sur le bouton.

Pour d’autres événements, vous pouvez lier en utilisant Interactivity triggers. Reportez-vous à l'exemple ici comment les utiliser pour se lier à ICommand dans ViewModel.


Comment puis-je désactiver le bouton lorsque (a) certaines zones de texte ne sont pas renseignées?

Le lien que vous avez posté ne fournit pas une implémentation complète de RelayCommand. Il manque au constructeur surchargé de définir le prédicat CanExecute qui joue un rôle clé dans l'activation/la désactivation du contrôle de l'interface utilisateur auquel votre commande est liée.

La liaison des zones de texte avec certaines propriétés dans ViewModel et dans CanExecute delegate renvoie la valeur false si l'une des propriétés liées est null ou vide, ce qui désactive automatiquement le contrôle auquel la commande est liée.


Implémentation complète de RelayCommand:

public class RelayCommand<T> : ICommand
{
    #region Fields

    readonly Action<T> _execute = null;
    readonly Predicate<T> _canExecute = null;

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
    /// </summary>
    /// <param name="execute">Delegate to execute when Execute is called on the command.  This can be null to just hook up a CanExecute delegate.</param>
    /// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
    public RelayCommand(Action<T> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<T> execute, Predicate<T> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion

    #region ICommand Members

    ///<summary>
    ///Defines the method that determines whether the command can execute in its current state.
    ///</summary>
    ///<param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    ///<returns>
    ///true if this command can be executed; otherwise, false.
    ///</returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute((T)parameter);
    }

    ///<summary>
    ///Occurs when changes occur that affect whether or not the command should execute.
    ///</summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    ///<summary>
    ///Defines the method to be called when the command is invoked.
    ///</summary>
    ///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    #endregion
}
65
Rohit Vats

L’utilisation de la commande relay présente l’avantage de pouvoir lier les commandes directement au ViewModels. En utilisant les commandes de manière à éviter d'écrire du code dans les vues codebehind.

Lorsque vous utilisez des commandes de relais, vous devrez fournir deux méthodes. Le premier indique si la commande peut être exécutée (par exemple, "CanExecuteSave"), le second étant chargé de l’exécution de la commande ("ExecuteSave").

4
Dennis Kassel