Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不使用命令调用ViewModel中的方法_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 不使用命令调用ViewModel中的方法

C# 不使用命令调用ViewModel中的方法,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我有以下情况: public class MyCommand : ICommand { MyViewModel _viewModel; public MyCommand(MyViewModel viewModel) { _viewModel = viewModel; } public bool CanExecute(object parameter) { return true; } publi

我有以下情况:

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属性中调用的方法名称


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

您可以使用MVVMLight中的RelayCommand或PRISM中的DelegateCommand。它们都将给出一种实现命令的通用方法。 甚至可以创建自己的公共命令类并使用它。参考下面的示例

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);
        }
    }
公共类视图模型:INotifyPropertyChanged
{
public BaseCommand GetDataCommand{get;set;}
公共视图模型()
{
GetDataCommand=新的BaseCommand(GetData);
}
私有void GetData(对象参数)
{
}  
}
公共类BaseCommand:ICommand
{
私有谓词_canExecute;
私人行动法;
公共事件事件处理程序CanExecuteChanged
{
添加
{
CommandManager.RequerySuggested+=值;
}
去除
{
CommandManager.RequerySuggested-=值;
}
}
public BaseCommand(操作方法,谓词canExecute=null)
{
_方法=方法;
_canExecute=canExecute;
}
公共布尔CanExecute(对象参数)
{
如果(_canExecute==null)
{
返回true;
}
返回_canExecute(参数);
}
public void Execute(对象参数)
{
_方法调用(参数);
}
}

您可以使用MVVMLight中的RelayCommand或PRISM中的DelegateCommand。它们都将给出一种实现命令的通用方法。 甚至可以创建自己的公共命令类并使用它。参考下面的示例

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);
        }
    }
公共类视图模型:INotifyPropertyChanged
{
public BaseCommand GetDataCommand{get;set;}
公共视图模型()
{
GetDataCommand=新的BaseCommand(GetData);
}
私有void GetData(对象参数)
{
}  
}
公共类BaseCommand:ICommand
{
私有谓词_canExecute;
私人行动法;
公共事件事件处理程序CanExecuteChanged
{
添加
{
CommandManager.RequerySuggested+=值;
}
去除
{
CommandManager.RequerySuggested-=值;
}
}
public BaseCommand(操作方法,谓词canExecute=null)
{
_方法=方法;
_canExecute=canExecute;
}
公共布尔CanExecute(对象参数)
{
如果(_canExecute==null)
{
返回true;
}
返回_canExecute(参数);
}
public void Execute(对象参数)
{
_方法调用(参数);
}
}
您可以使用中的“”操作从视图中调用视图模型上的方法。它看起来像这样:

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

但是,使用命令仍然被认为是最佳实践。正如Ayyappan提到的,您可以使用这样的库,这样就不必编写自己的ICommand实现

PS:另请参见

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

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

但是,使用命令仍然被认为是最佳实践。正如Ayyappan提到的,您可以使用这样的库,这样就不必编写自己的ICommand实现


PS:另请参见

1)这并不是最好的方法2)您可以直接调用该方法,但您必须跳过UI中的白痴环才能执行此操作,这比使用ICommand模式更昂贵。您还将逻辑分为两部分,即
视图
视图模型
,如果有人来维护此代码,他们必须查看两个位置,而不是一个位置,即
ViewModel
。1)这不是最好的方法2)您可以直接调用此方法,但是,您必须跳过UI中的白痴圈来完成比使用ICommand模式更昂贵的操作。您还将逻辑拆分为两部分,即
View
ViewModel
,如果有人愿意来维护此代码,则他们必须在2个位置而不是一个位置查看,即
ViewModel