ICommand帮助替换按钮事件

时间:2014-04-07 15:07:01

标签: wpf mvvm observablecollection icommand

我刚刚收到有关ICommands的一些信息,

在我的WPF应用程序中,我有一些添加到ObservableCollection的onClick事件。所以(ObservableCollection.Add()

但是,我还有2个类似的事件要添加到集合中。所以我听说我可以使用ICommand接口“执行”来添加/编辑/删除等,所以我不需要这些单独的事件。

有人能为我提供一个如何在MVVM中执行此操作的示例。 (所有添加都在我的ViewModel中)

由于

1 个答案:

答案 0 :(得分:1)

您可能想要查看" RelayCommand" - 它是ICommand的通用实现,可以简化您的视图模型代码,允许您为ICommand"执行"指定代理。和" CanExecute"方法。您将在网络上找到大量实现,但这是我使用的实现:

public class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Predicate<object> _canExecute;

    public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        this._execute = execute;
        this._canExecute = canExecute;
    }

    public virtual bool CanExecute(object parameter)
    {
        return this._canExecute == null || this._canExecute(parameter);
    }

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

    public virtual void Execute(object parameter)
    {
        this._execute(parameter);
    }
}

在您的VM中,公开如下命令: -

public ICommand FooCommand
{
    get
    {
        if (_fooCommand == null)
        {
            _fooCommand = new RelayCommand(ExecuteFooCommand, CanDoFooCommand);
        }
        return _fooCommand;
    }
}

private void ExecuteFooCommand(object commandParameter)
{
    // Code to execute the command.
}

private bool CanDoFooCommand()
{
    // Code that indicates whether the command can be executed.
    // This will manifest itself in the view by enabling/disabling the button.
}

由于RelayCommand ctr参数是委托,你当然可以做这样的事情: -

new RelayCommand(o => { // do something }, o => true);

最后,将命令绑定到视图按钮: -

<Button Content="Click me" Command="{Binding FooCommand}" ... />

您还可以将参数传递给命令委托: -

<Button Content="Click me" Command="{Binding FooCommand}" CommandParamter="123" />

(从内存中写出来可能不是100%语法正确!)

更进一步......

为了简化操作,我使用动态属性将VM命令公开给视图。在我的VM基类中,我有以下属性: -

    public dynamic Commands
    {
        get
        {
            return _commands;
        }
    }

然后在VM的构造函数中,我可以创建它的所有命令: -

Commands.FooCommand = new RelayCommand(.....
Commands.BarCommand = ..etc..

在我的XAML中,我绑定了这样的命令: - Command={Binding Commands.FooCommand}。 这是一个节省时间的因为它只是意味着我可以根据我的需要从单个属性中挂起尽可能多的命令,而不是将每个命令作为单独的属性公开,如我之前的示例所示。