ICommand的MVVM实施ICommand的MVVM实施(ICommand MVVM imple

2019-05-05 01:12发布

所以在这个特定MVVM实现我做的,我需要几个命令。 我真的累了实现ICommand的类别逐一的,所以我想出了一个解决方案,但我不知道它有多好,所以这里的任何WPF专家的输入将不胜感激。 如果你能提供一个更好的解决方案,甚至更好。

我所做的是一个单一的ICommand类和两名代表其采取的对象作为参数,一个代表是无效的(对于OnExecute),其他的布尔(用于OnCanExecute)。 所以在我的ICommand(这是由视图模型类的称呼)的构造我的两个方法发送,并在每个方法的ICommand调用我代表们的方法。

它的作品真的很好,但我不知道这是一个糟糕的方式做到这一点,或者如果有一个更好的办法。 下面是完整的代码,任何输入将不胜感激,甚至是负的,但请有建设性的。

视图模型:

public class TestViewModel : DependencyObject
{
    public ICommand Command1 { get; set; }
    public ICommand Command2 { get; set; }
    public ICommand Command3 { get; set; }

    public TestViewModel()
    {
        this.Command1 = new TestCommand(ExecuteCommand1, CanExecuteCommand1);
        this.Command2 = new TestCommand(ExecuteCommand2, CanExecuteCommand2);
        this.Command3 = new TestCommand(ExecuteCommand3, CanExecuteCommand3);
    }

    public bool CanExecuteCommand1(object parameter)
    {
        return true;
    }

    public void ExecuteCommand1(object parameter)
    {
        MessageBox.Show("Executing command 1");
    }

    public bool CanExecuteCommand2(object parameter)
    {
        return true;
    }

    public void ExecuteCommand2(object parameter)
    {
        MessageBox.Show("Executing command 2");
    }

    public bool CanExecuteCommand3(object parameter)
    {
        return true;
    }

    public void ExecuteCommand3(object parameter)
    {
        MessageBox.Show("Executing command 3");
    }
}

ICommand的:

public class TestCommand : ICommand
{
    public delegate void ICommandOnExecute(object parameter);
    public delegate bool ICommandOnCanExecute(object parameter);

    private ICommandOnExecute _execute;
    private ICommandOnCanExecute _canExecute;

    public TestCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod)
    {
        _execute = onExecuteMethod;
        _canExecute = onCanExecuteMethod;
    }

    #region ICommand Members

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

    public bool CanExecute(object parameter)
    {
        return _canExecute.Invoke(parameter);
    }

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

    #endregion
}

Answer 1:

这几乎等同于如何卡尔Shifflet证明一个RelayCommand ,其中Execute火灾预定Action<T> 一个一流的解决方案,如果你问我。

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

    public RelayCommand(Predicate<object> canExecute, Action<object> execute)
    {
        this._canExecute = canExecute;
        this._execute = execute;
    }

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

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

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

这可以被用来作为...

public class MyViewModel
{
    private ICommand _doSomething;
    public ICommand DoSomethingCommand
    {
        get
        {
            if (_doSomething == null)
            {
                _doSomething = new RelayCommand(
                    p => this.CanDoSomething,
                    p => this.DoSomeImportantMethod());
            }
            return _doSomething;
        }
    }
}

阅读更多:
约什-史密斯(介绍人的RelayCommand ):模式- WPF应用程序与MVVM设计模式



Answer 2:

我写这篇文章对ICommand接口。

这个想法-建立一个普遍的命令有两个代表:当一个人被称为ICommand.Execute (object param)被调用时,第二检查你是否能执行命令的状态(ICommand.CanExecute (object param))

需要的方法来切换事件CanExecuteChanged 。 它从用于切换的状态下的用户界面元素称为CanExecute()命令。

public class ModelCommand : ICommand
{
    #region Constructors

    public ModelCommand(Action<object> execute)
        : this(execute, null) { }

    public ModelCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion

    #region ICommand Members

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return _canExecute != null ? _canExecute(parameter) : true;
    }

    public void Execute(object parameter)
    {
        if (_execute != null)
            _execute(parameter);
    }

    public void OnCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }

    #endregion

    private readonly Action<object> _execute = null;
    private readonly Predicate<object> _canExecute = null;
}


Answer 3:

我刚刚创建了一个小例子说明如何实现约定优于配置风格的命令。 然而,它需要Reflection.Emit的()可用。 支持的代码看起来可能有点怪异,但一旦写入可多次使用。

预告:

public class SampleViewModel: BaseViewModelStub
{
    public string Name { get; set; }

    [UiCommand]
    public void HelloWorld()
    {
        MessageBox.Show("Hello World!");
    }

    [UiCommand]
    public void Print()
    {
        MessageBox.Show(String.Concat("Hello, ", Name, "!"), "SampleViewModel");
    }

    public bool CanPrint()
    {
        return !String.IsNullOrEmpty(Name);
    }
}

}

更新 :现在似乎有存在像一些图书馆http://www.codeproject.com/Articles/101881/Executing-Command-Logic-in-a-View-Model能够解决的ICommand的样板代码的问题。



Answer 4:

@Carlo我很喜欢你的这个实现,但我想分享我的版本,以及如何在我的视图模型使用

首先实施的ICommand

public class Command : ICommand
{
    public delegate void ICommandOnExecute();
    public delegate bool ICommandOnCanExecute();

    private ICommandOnExecute _execute;
    private ICommandOnCanExecute _canExecute;

    public Command(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod = null)
    {
        _execute = onExecuteMethod;
        _canExecute = onCanExecuteMethod;
    }

    #region ICommand Members

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

    public bool CanExecute(object parameter)
    {
        return _canExecute?.Invoke() ?? true;
    }

    public void Execute(object parameter)
    {
        _execute?.Invoke();
    }

    #endregion
}

请注意,我已删除从ICommandOnExecuteICommandOnCanExecute参数,并添加一个空的构造函数

然后在视图模型使用

public Command CommandToRun_WithCheck
{
    get
    {
        return new Command(() =>
        {
            // Code to run
        }, () =>
        {
            // Code to check to see if we can run 
            // Return true or false
        });
    }
}

public Command CommandToRun_NoCheck
{
    get
    {
        return new Command(() =>
        {
            // Code to run
        });
    }
}

我只是觉得这种方式更清洁,因为我不需要给变量赋值,然后实例,这一切在一气呵成完成。



文章来源: ICommand MVVM implementation