Вот почему я не использую реализацию DelegateCommand
в Prism. Я всегда ненавидел подход на основе обратного вызова для включения / выключения команд. Это совершенно не нужно, и, насколько я могу судить, его единственное (и довольно сомнительное) «преимущество» заключается в том, что оно согласуется с тем, как выполняется само выполнение. Но это всегда казалось мне бессмысленным, потому что выполнение и включение / отключение явно очень разные: кнопка знает, когда она хочет выполнить команду, но не знает, когда ее статус мог измениться.
Так что я всегда пишу что-то вроде этого:
public class RelayCommand : ICommand
{
private bool _isEnabled;
private Action _onExecute;
public RelayCommand(Action executeHandler)
{
_isEnabled = true;
_onExecute = executeHandler;
}
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
public bool CanExecute(object parameter)
{
return _isEnabled;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_onExecute();
}
}
(При необходимости вы можете изменить это, чтобы использовать слабые ссылки для выполнения обработчиков событий изменения, как это делает Prism.)
Но чтобы ответить на ваш вопрос: как вообще работает обратный вызов? DelegateCommand
Prism предлагает метод RaiseCanExecuteChanged
, который вы можете вызвать, чтобы попросить его вызвать событие, которое заставит тех, кто вызывает команды, запросить CanExecute
вашей команды. Учитывая то, что вы должны сообщать DelegateCommand
каждый раз, когда ваш включенный статус меняется, я не вижу значимого преимущества подхода, основанного на обратном вызове. (Хотя иногда вы видите модель широковещания - устроение так, что любое изменение статуса где-либо уведомляет все команды, вызывающие! В этом случае обратный вызов полезен, потому что это означает, что не имеет значения, если вы не знаете, что на самом деле изменилось. Но запрашивать каждую команду мне неприятно.)