Почему RelayCommand

В последнее время я много программировал на WPF, но мои View и ViewModel на данный момент не разделены. Ну, это частично. Все мои привязки, относящиеся к тексту в текстовых полях, содержимому для меток, спискам в сетках данных,... выполняются обычными свойствами с событием NotifyPropertyChanged.

Все мои события, связанные с обработкой нажатий кнопок или изменением текста, выполняются путем связывания событий. Теперь я хотел начать работать с командами и нашел эту статью: http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute. В нем есть объяснение того, как настроить MVVM, но я запутался с RelayCommand,

Какую работу это делает? Это применимо для всех команд в моей форме? Как сделать кнопку отключенной, если (а) некоторые текстовые поля не заполнены?


РЕДАКТИРОВАТЬ 1:

Хорошее объяснение: "Это можно использовать для всех команд в моей форме?" здесь ответили: /questions/44205135/pochemu-relaycommand/44205157#44205157

Вот код, который у меня пока есть: https://stackru.com/a/22289358/3357699

2 ответа

Решение

Команды используются для отделения семантики и объекта, который вызывает команду, от логики, которая выполняет команду, т.е. он отделяет компонент пользовательского интерфейса от логики, которую необходимо выполнить при вызове команды. Таким образом, вы можете тестировать бизнес-логику отдельно, используя контрольные примеры, а также ваш код пользовательского интерфейса слабо связан с бизнес-логикой.

Теперь, как говорится, давайте выберем ваши вопросы один за другим:

Какую работу это делает?

Я добавил детали выше. Надеюсь, что это очищает использование команд.


Это можно использовать для всех команд в моей форме?

Некоторые элементы управления выставляют Command DependencyProperty, такие как Button, MenuItem и т. Д., Для которых зарегистрировано какое-то событие по умолчанию. Для кнопки это Click событие. Итак, если вы связываете ICommand объявленный в ViewModel с Command's Button DP, он будет вызываться при каждом нажатии кнопки.

Для других событий вы можете связать с помощью Interactivity triggers, Обратитесь к примеру здесь, как использовать их для привязки к ICommand в ViewModel.


Как сделать кнопку отключенной, если (а) некоторые текстовые поля не заполнены?

Ссылка, которую вы разместили, не обеспечивает полную реализацию RelayCommand, Ему не хватает перегруженного конструктора для установки CanExecute Предикат, который играет ключевую роль в включении / отключении элемента управления пользовательского интерфейса, к которому привязана ваша команда.

Свяжите TextBox с некоторыми свойствами в ViewModel и в CanExecute Делегат возвращает ложь, если какое-либо из свойств связанного является нулевым или пустым, что автоматически отключает элемент управления, к которому привязана команда.


Полная реализация 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
}

Преимущество использования команды relay заключается в том, что вы можете привязывать команды непосредственно к моделям представления. Используя команды таким образом, вы избегаете написания кода в представлении codehhind.

При использовании команд реле вы должны будете предоставить два метода. Первый предоставляет значение, может ли команда быть выполнена (например, "CanExecuteSave"), в то время как другой будет отвечать за выполнение команды ("ExecuteSave").

Другие вопросы по тегам