Принудительно пересмотреть ICommand CanExecute при открытии контекстного меню

Я знаю, что могу принудительно переоценить CanExecute в модели представления, однако для этого требуется, чтобы модель представления зарегистрировалась во всех связанных событиях изменения данных, что не всегда возможно.

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

Чтобы сделать это, я могу подключить событие открытия контекстного меню и вызвать модель представления, чтобы вызвать RaiseCanExecuteChanged для каждой ICommand, которую использует контекстное меню, но это утомительно и против MVVM. Мне интересно, есть ли более простой способ добиться этого?

1 ответ

Решение

Да, есть. Используйте эту реализацию ICommand. Он переоценивает каждое взаимодействие, в вашем случае "Открытие контекстного меню". Это не так эффективно с точки зрения производительности, но если у вас нет сотен команд, тогда следует выполнить работу:

public class Command<TArgs> : ICommand
{
    public Command(Action<TArgs> exDelegate)
    {
        _exDelegate = exDelegate;
    }

    public Command(Action<TArgs> exDelegate, Func<TArgs, bool> canDelegate)
    {
        _exDelegate = exDelegate;
        _canDelegate = canDelegate;
    }

    protected Action<TArgs> _exDelegate;
    protected Func<TArgs, bool> _canDelegate;

    #region ICommand Members

    public bool CanExecute(TArgs parameter)
    {
        if (_canDelegate == null)
            return true;

        return _canDelegate(parameter);
    }

    public void Execute(TArgs parameter)
    {
        if (_exDelegate != null)
        {
            _exDelegate(parameter);
        }
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    bool ICommand.CanExecute(object parameter)
    {
        if (parameter != null)
        {
            var parameterType = parameter.GetType();
            if (parameterType.FullName.Equals("MS.Internal.NamedObject"))
                return false;
        }

        return CanExecute((TArgs)parameter);
    }

    void ICommand.Execute(object parameter)
    {
        Execute((TArgs)parameter);
    }

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