强制在上下文菜单打开时重新评估ICommand CanExecute

时间:2013-08-14 03:25:26

标签: wpf commandbinding canexecute

我知道我可以在视图模型中强制重新评估CanExecute,但是,这需要视图模型注册到所有相关的数据更改事件,这可能并不总是可行的。

由于命令仅在上下文菜单中使用,并且在上下文菜单打开期间,无法更改影响CanExecute的数据,仅在打开上下文菜单时重新评估CanExecute就足够了。

要做到这一点,我可以连接上下文菜单打开事件并调用视图模型在上下文菜单使用的每个ICommand上调用RaiseCanExecuteChanged,但它是乏味且反MVVM。我想知道是否有更简单的方法来实现这一目标?

1 个答案:

答案 0 :(得分:3)

是的。使用此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
}