RelayCommand<enum> 上的 RaiseCanExecuteChanged() 不会导致调用 CanExecute()

RaiseCanExecuteChanged() on a RelayCommand<enum> doesn't cause CanExecute() to be called

我的第一个问题来了。

在带有 MVVM Light 的 UWP 应用程序中,我试图定义只有一个命令,其中包含一个枚举参数以响应视图中的所有按钮交互。但是按钮仍处于禁用状态并且没有响应。

我已经为命令定义了参数

public enum ButtonKey
{
    Connect = 0,
    Disconnect = 1
}

然后由 MainViewModel 使用 class

public class MainViewModel : ViewModelBase
{
    RelayCommand<ButtonKey> buttonPressed;
    public RelayCommand<ButtonKey> ButtonPressed
    {
        get => buttonPressed;
        set => buttonPressed = value;
    }

    public MainViewModel()
    {
        buttonPressed = new RelayCommand<ButtonKey> (ButtonPressed_Execute, ButtonPressed_CanExecute);
    }

    bool ButtonPressed_CanExecute(ButtonKey arg)
    {
        bool retValue = false;
        switch (arg)
        {
            // The following conditions are just for testing
            case ButtonKey.Connect:
                retValue = true;
                break;
            case ButtonKey.Disconnect:
                retValue = false;
                break;
        }
        return retValue;
    }

    void ButtonPressed_Execute(ButtonKey obj)
    {
        // another switch() case:
    }
}

那么xaml代码如下:

<CommandBar>
    <AppBarButton Label="Connect" Command="{Binding ButtonPressed}">
        <AppBarButton.CommandParameter>
            <viewModel:ButtonKey>Connect</viewModel:ButtonKey>
        </AppBarButton.CommandParameter>
    </AppBarButton>
    <AppBarButton Label="Disconnect" Command="{Binding ButtonPressed}">
        <AppBarButton.CommandParameter>
            <viewModel:ButtonKey>Disconnect</viewModel:ButtonKey>
    </AppBarButton.CommandParameter>
</AppBarButton>

即使在 MainViewModel 构造函数中调用 buttonPressed.RaiseCanExecuteChanged(),也不会调用 ButtonPressed_CanExecute(ButtonKey arg) 方法。

我认为都是因为命令参数使用的枚举类型导致的,但我想不通为什么。任何帮助将不胜感激。

我查看了MvvmLight的源代码,发现了问题。在 RelayCommand<T>'s source 中,您会在 CanExecute 方法中找到以下检查:

if (parameter == null || parameter is T)
{
    return (_canExecute.Execute((T)parameter));
}

出于某种原因,该方法的枚举 parameter 是一个 int,而不是执行检查时枚举的实例。因此,第二次检查将失败。

如果您更新代码以使用 int,它将按预期工作:

public RelayCommand<int> ButtonPressed { get; set; }

public MainViewModel()
{
    ButtonPressed = new RelayCommand<int>(ButtonPressed_Execute, ButtonPressed_CanExecute);            
}

bool ButtonPressed_CanExecute(int arg)
{
    bool retValue = false;
    switch (arg)
    {
        // The following conditions are just for testing
        case (int) ButtonKey.Connect:
            retValue = true;
            break;
        case (int) ButtonKey.Disconnect:
            retValue = false;
            break;
    }
    return retValue;
}

void ButtonPressed_Execute(int  obj)
{
    // another switch() case:
}

我觉得这很令人惊讶,我想这应该作为 MvvmLight 中的一个错误来解决。

尝试使用 x:static 标记扩展设置命令参数

<AppBarButton Label="Connect" 
              Command="{Binding ButtonPressed}"
              CommandParameter="{x:Static viewModel:ButtonKey.Connect}" />