在没有命令的情况下在ViewModel中调用方法

时间:2015-01-14 14:43:32

标签: c# wpf xaml mvvm

我有以下情况:

public class MyCommand : ICommand
{
    MyViewModel _viewModel;

    public MyCommand(MyViewModel viewModel)
    {
        _viewModel = viewModel;
    }

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

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _viewModel.SomeMethod();
    }
}

基本上,当单击一个按钮时,此命令将简单地调用ViewModel中的方法。 CanExecute 始终返回true。

问题在于,即使这通常被认为是最好的做事方式,但它并不优雅。它引出了为什么我需要一个命令来完成这个非常简单的过程的问题。

为什么我不能跳过命令,直接调用该方法?

我已经考虑过这一点,我能看到实现这一目标的唯一方法是创建一个命令,我可以在 CommandParameter <中指定我想要调用的方法名称/ strong>我按钮上的属性。

我希望其他人可以为这个问题提供一个优雅的解决方案。

2 个答案:

答案 0 :(得分:4)

您可以使用CallMethodAction中的“Blend SDK”操作从视图中调用视图模型上的方法。它看起来像这样:

<Button ...>
  <i:Interaction.Triggers> 
    <i:EventTrigger EventName="Click"> 
      <ei:CallMethodAction MethodName="MyMethod" TargetObject="{Binding}" /> 
    </i:EventTrigger> 
  </i:Interaction.Triggers> 
</Button>

然而,仍然认为使用命令的最佳做法。正如Ayyappan所提到的,您可以使用像MVVM Light Toolkit这样的库,这样您就不必编写自己的ICommand实现了。

PS:另见WPF: MVVM: Command vs CallMethodAction?

答案 1 :(得分:2)

您可以使用来自MVVMLight的RelayCommand或来自PRISM的DelegateCommand。它们都将提供一种实现命令的通用方法。 甚至你可以创建自己的Common命令类并使用它。请参阅下面的示例。

public class ViewModel : INotifyPropertyChanged
    {
        public BaseCommand GetDataCommand { get; set; }

        public ViewModel()
        {
            GetDataCommand = new BaseCommand(GetData);            
        }

        private void GetData(object param)
        {

        }  
    }

    public class BaseCommand : ICommand
    {
        private Predicate<object> _canExecute;
        private Action<object> _method;
        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }

        public BaseCommand(Action<object> method, Predicate<object> canExecute=null)
        {
            _method = method;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecute == null)
            {
                return true;
            }

            return _canExecute(parameter);
        }

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