5

在我的项目中,我想使用 MVVM (& Commands)。我已经开始学习 ICommand 的命令和实现。

我想创建ICommand没有参数的实现。 (触发数据加载/数据刷新等 - 我不需要任何参数来执行此操作,因此尝试创建不带参数的命令似乎很自然)

这是我正在使用的代码:

using System.Windows.Input;

public class NoParameterCommand : ICommand
{
    private Action executeDelegate = null;
    private Func<bool> canExecuteDelegate = null;
    public event EventHandler CanExecuteChanged = null;

    public NoParameterCommand(Action execute)
    {
        executeDelegate = execute;
        canExecuteDelegate = () => { return true; };
    }
    public NoParameterCommand(Action execute, Func<bool> canExecute)
    {
        executeDelegate = execute;
        canExecuteDelegate = canExecute;
    }

    public bool CanExecute()
    {
        return canExecuteDelegate();
    }
    public void Execute()
    {
        if (executeDelegate != null)
        {
            executeDelegate();
        }
    }
}

但是我收到了关于没有以正确的方式实现 ICommand 接口的错误('XXX.YYYY.NoParameterCommand' does not implement interface member 'System.Windows.Input.ICommand.Execute(object)'

所以我想这样做:

CanExecute(添加了和中缺少的参数Execute

public class NoParameterCommand : ICommand
{
    ...omitted - no changes here...

    public bool CanExecute(object parameter) //here I added parameter
    {
        return canExecuteDelegate();
    }
    public void Execute(object parameter)    //and here
    {
        if (executeDelegate != null)
        {
            executeDelegate();
        }
    }
}
  1. 这是一个好方法吗?
  2. 我应该使用其他方式吗?(如果是这样,我应该怎么做?)
4

3 回答 3

7
  1. 这是一个很好的方法。
  2. 不,您不应该使用其他方式。

补充建议:

再次考虑这一点,我将通过引入额外的层次结构来改进你的架构 whereCanExecute()Execute()are abstract。从该类派生调用委托的命令类。

这样,您可以稍后决定是通过委托还是通过子类化您的基本命令类来为无参数命令提供逻辑。

于 2013-10-14T12:41:24.330 回答
5

我不确定你关心的是什么。ICommand忽略界面中的参数是很常见的。

如果您真的想要没有参数的方法,您可以显式(而不是隐式)实现接口CanExecuteExecute这些ICommand方法仍然存在,但对于从外部查看您的对象的任何人来说,他们将无法看到这些方法:

bool ICommand.CanExecute(object parameter) { this.CanExecute(); }

public bool CanExecute()
{
  //do work
}

您实际上是在隐藏接口实现。如果有人想直接CanExecute从接口调用该方法,他们必须键入 cast toICommand才能做到这一点。这样做你真的没有任何收获,但是如果你关心你的类在外部开发者眼中的样子(例如你正在开发一个 API),那么当你让他们知道时,这可以使它看起来更干净一些您不需要任何参数。

于 2013-10-14T12:47:06.473 回答
2

我个人更喜欢这种方式:

public class MyCommand : ICommand
{
    private static bool True() { return true; }

    private readonly Action _execute;
    private Func<bool> _canExecute;
    private Func<bool> _isVisible;

    public event EventHandler IsVisibleChanged;
    public event EventHandler CanExecuteChanged;

    public MyCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
    {
        _execute = execute;
        _canExecute = canExecute ?? True;
        _isVisible = isVisible ?? True;
    }

    public void Execute()
    {
        _execute();
    }

    public Func<bool> CanExecute
    {
        set
        {
            _canExecute = value ?? True;
            CanExecuteChanged(this, new EventArgs());
        }
        get { return _canExecute; }
    }

    public Func<bool> IsVisible
    {
        set
        {
            _isVisible = value ?? True;
            IsVisibleChanged(this, new EventArgs());
        }
        get { return _isVisible; }
    }

    bool ICommand.CanExecute(object parameter)
    {
        return CanExecute();
    }

    void ICommand.Execute(object parameter)
    {
        Execute();
    }
}

然而,由于代表通常不会改变,我更喜欢不可变的版本:

[ImmutableObject(true)]
public class MyImmutableCommand : ICommand
{
    private static bool True() { return true; }

    private readonly Action _execute;
    private readonly Func<bool> _canExecute;
    private readonly Func<bool> _isVisible;

    [Obsolete("Will not be invoked, because the implementation never changes.")]
    public event EventHandler CanExecuteChanged;

    public MyImmutableCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
    {
        _execute = execute;
        _canExecute = canExecute ?? True;
        _isVisible = isVisible ?? True;
    }

    public bool CanExecute()
    {
        return _canExecute(); 
    }

    public bool IsVisible()
    {
        return _isVisible(); 
    }

    public void Execute()
    {
        _execute();
    }

    bool ICommand.CanExecute(object parameter)
    {
        return CanExecute();
    }

    void ICommand.Execute(object parameter)
    {
        Execute();
    }
}
于 2014-12-07T12:16:58.553 回答