如何在没有参数的情况下实现ICommand

时间:2013-10-14 12:38:16

标签: c# mvvm windows-phone-8 icommand

在我的项目中,我想使用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)'

所以我想这样做:

(添加了CanExecuteExecute中缺少的参数)

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. 我应该使用另一种方式吗? (如果是这样,我应该做什么?)

3 个答案:

答案 0 :(得分:6)

  1. 这是一个很好的方法。
  2. 不,你不应该用另一种方式。
  3. 其他建议:

    再次考虑这一点,我会通过引入CanExecute()Execute()abstract的其他层次结构级别来改进您的体系结构。从该类派生出调用委托的命令类。

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

答案 1 :(得分:5)

我不确定你的顾虑是什么。通常忽略ICommand接口中的参数。

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

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

public bool CanExecute()
{
  //do work
}

您实际上是隐藏了界面实现。如果有人想直接从界面调用CanExecute方法,他们必须输入强制转换为ICommand才能执行此操作。你这样做真的没有任何好处,但如果你关心你的课程对外部开发人员的看法(例如你正在开发一个API),那么这可以让你看起来更清洁,因为你让他们知道你不需要任何参数。

答案 2 :(得分: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();
    }
}