WPF ViewModel命令CanExecute问题

Lia*_*amV 12 wpf binding command contextmenu icommand

我的View Model上的Context Menu命令有些困难.

我正在为View Model中的每个命令实现ICommand接口,然后在View(MainWindow)的资源中创建ContextMenu,并使用MVVMToolkit中的CommandReference访问当前的DataContext(ViewModel)命令.

当我调试应用程序时,似乎除了创建窗口之外,没有调用命令上的CanExecute方法,因此我的Context MenuItems没有像我期望的那样启用或禁用.

我已经制作了一个简单的样本(附在这里),它表明了我的实际应用并总结如下.任何帮助将不胜感激!

这是ViewModel

namespace WpfCommandTest
{
    public class MainWindowViewModel
    {
        private List<string> data = new List<string>{ "One", "Two", "Three" };

        // This is to simplify this example - normally we would link to
        // Domain Model properties
        public List<string> TestData
        {
            get { return data; }
            set { data = value; }
        }

        // Bound Property for listview
        public string SelectedItem { get; set; }

        // Command to execute
        public ICommand DisplayValue { get; private set; }

        public MainWindowViewModel()
        {
            DisplayValue = new DisplayValueCommand(this);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

DisplayValueCommand是这样的:

public class DisplayValueCommand : ICommand
{
    private MainWindowViewModel viewModel;

    public DisplayValueCommand(MainWindowViewModel viewModel)
    {
        this.viewModel = viewModel;
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        if (viewModel.SelectedItem != null)
        {
            return viewModel.SelectedItem.Length == 3;
        }
        else return false;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        MessageBox.Show(viewModel.SelectedItem);
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

最后,视图在Xaml中定义:

<Window x:Class="WpfCommandTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfCommandTest"
    xmlns:mvvmtk="clr-namespace:MVVMToolkit"
    Title="Window1" Height="300" Width="300">

    <Window.Resources>

        <mvvmtk:CommandReference x:Key="showMessageCommandReference" Command="{Binding DisplayValue}" />

        <ContextMenu x:Key="listContextMenu">
            <MenuItem Header="Show MessageBox" Command="{StaticResource showMessageCommandReference}"/>
        </ContextMenu>

    </Window.Resources>

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <ListBox ItemsSource="{Binding TestData}" ContextMenu="{StaticResource listContextMenu}" 
                 SelectedItem="{Binding SelectedItem}" />
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

Tho*_*que 21

要完成Will的答案,这里是CanExecuteChanged事件的"标准"实现:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}
Run Code Online (Sandbox Code Playgroud)

(来自Josh Smith的RelayCommand课程)

顺便说一下,您应该考虑使用RelayCommandDelegateCommand:您很快就会厌倦为ViewModels的每个命令创建新的命令类...