Mvvmlight RelayCommand中canExecute的怪异行为

本文关键字:RelayCommand canExecute Mvvmlight | 更新日期: 2023-09-27 18:02:30

我正在学习Mvvmlight,并且对RelayCommand的canExecute很困惑。

基本上,我在view中有一个Button和一个PasswordBox,在viewModel中有一个Command。我想要的是禁用按钮,如果密码框为空。我的解决方案是将PasswordBox作为commandparmeter传递给按钮,然后在canExecute方法中接收PasswordBox并指定它是空还是空。我首先声明一个命令:

public ICommand CommandClear { get; private set; }

然后在Class Constructor:

中实例化它
CommandConfirm = new RelayCommand<object>((p) => ConfirmExecute(p), (p) => ConfirmCanExecute(p));

最后实现canExecute方法如下:

private bool ConfirmCanExecute(object parameter)
{
    bool isExecuable = false;
    var passwordBox = parameter as PasswordBox;
    if (!string.IsNullOrEmpty(passwordBox.Password))
        isExecuable = true;
    return isExecuable;
}

上面的canExecute方法不起作用,因为System.Reflection.TargetInvocationException会在PresentationFramework.dll中抛出一个未处理的异常。

所以我尝试用try...catch来包装上面的代码,这一次,它就像魔法一样工作:
        try
        {
            var passwordBox = parameter as PasswordBox;
            if (!string.IsNullOrEmpty(passwordBox.Password))
                isExecuable = true;
            return isExecuable;
        }
        catch
        {
            return isExecuable;
        }

我对canExecute的这种行为很困惑,有什么想法吗?

Mvvmlight RelayCommand中canExecute的怪异行为

您是否在这一行的堆栈上声明p,并且在调用处理程序时它是否仍然存在?

CommandConfirm = new RelayCommand<object>((p) => ConfirmExecute(p), (p) => ConfirmCanExecute(p));

因为不正确的命令绑定肯定会导致this返回null,从而产生您所看到的错误。

var passwordBox = parameter as PasswordBox;

其次,为什么让ViewModel以这种方式直接操作View ?简单地将Password字段绑定到ViewModel,然后ViewModel的CanExecute处理程序就变成了一行代码,不是吗?

return !String.IsNullOrEmpty(this.Password);