Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.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# WPF命令-视图与模型的关系_C#_Wpf_Mvvm - Fatal编程技术网

C# WPF命令-视图与模型的关系

C# WPF命令-视图与模型的关系,c#,wpf,mvvm,C#,Wpf,Mvvm,我试图更好地理解用于WPF开发的MVVM设计模式,这是本主题中的一个基本问题 假设我实现了模型,它得到了一个执行主要操作的方法。在视图中,我想创建一个按钮,按下该按钮时将激活此操作。为了做到这一点,我需要将Click事件与事件处理程序相关联,实际上,它只是假设调用model方法 问题是,据我所知,视图甚至不认为知道模型。那么,我如何才能使视图中的按钮执行我想要的操作呢?您需要使用该界面,并提供一个实现,我建议您在MSDN上执行该实现 在ViewModel中,您将创建ICommand的实例,例如按

我试图更好地理解用于WPF开发的MVVM设计模式,这是本主题中的一个基本问题

假设我实现了模型,它得到了一个执行主要操作的方法。在视图中,我想创建一个按钮,按下该按钮时将激活此操作。为了做到这一点,我需要将
Click
事件与事件处理程序相关联,实际上,它只是假设调用model方法

问题是,据我所知,视图甚至不认为知道模型。那么,我如何才能使视图中的按钮执行我想要的操作呢?

您需要使用该界面,并提供一个实现,我建议您在MSDN上执行该实现

在ViewModel中,您将创建
ICommand
的实例,例如
按钮单击
,其外观类似(基于RelayCommand):

然后在xaml中绑定到
按钮单击

<Button Text="Click" Command="{Binding ButtonClick}" />

您需要使用该接口,并提供一个实现,我建议您在MSDN上实现

在ViewModel中,您将创建
ICommand
的实例,例如
按钮单击
,其外观类似(基于RelayCommand):

然后在xaml中绑定到
按钮单击

<Button Text="Click" Command="{Binding ButtonClick}" />

这就是视图模型的用武之地。首先,您应该考虑使用命令而不是事件处理程序。使用命令,您可以将“操作”绑定到按钮,而不是将事件硬编码到单击事件。像这样:

<Button Command="{Binding Path=ActionCommand}"/>

这意味着您的视图并不真正知道ViewModel的类型,只是它有一个名为ActionCommand的命令属性。要设置视图模型,请使用view.Datacontext。这可以通过几种不同的方式实现。这里也可以使用依赖注入。另一种解决方案是使用ViewModelLocator,它使用定位器模式将视图连接到其ViewModel。

这就是视图模型的作用所在。首先,您应该考虑使用命令而不是事件处理程序。使用命令,您可以将“操作”绑定到按钮,而不是将事件硬编码到单击事件。像这样:

<Button Command="{Binding Path=ActionCommand}"/>

这意味着您的视图并不真正知道ViewModel的类型,只是它有一个名为ActionCommand的命令属性。要设置视图模型,请使用view.Datacontext。这可以通过几种不同的方式实现。这里也可以使用依赖注入。另一种解决方案是使用ViewModelLocator,它使用定位器模式将视图连接到其ViewModel。

在您的模型中,您具有以下功能:

class MainWindowModel
{
   public void MyAction()
   {...}
}
在ViewModel的构造函数中,创建模型的实例,如:

class MainWindowViewModel
{
   private readonly MainWindowModel mainWindowModel;

   public MainWindowViewModel()
   {
      this.mainWindowModel = new MainWindowModel();
   }
然后您就有了一个
ICommand
的实现,比如RelayCommand:

public class ViewModel
{
    public ViewModel()
    {
        this.ButtonClick = new RelayCommand(_ => this.DoSomething());
    }

    public ICommand ButtonClick { get; set; }

    public void DoSomething()
    {
        // Something...
    }
}
public class RelayCommand : ICommand
    {
        private readonly Action<object> execute;
        private readonly Predicate<object> canExecute;

        public RelayCommand(Action<object> exectue, Predicate<object> canExecute = null)
        {
            if (exectue == null)
                throw new ArgumentNullException("exectue");
            this.execute = exectue;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return this.canExecute == null || this.canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            this.execute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }
当您实现
INotifyPropertyChanged
-接口时,得到的OnPropertyChanged事件

 public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
在ViewModel的构造函数中实例化MyCommand,如

this.MyCommand = new RelayCommand(MyCommandExecute);
然后必须在viewmodel中创建一个方法,在其中调用模型的MyAction方法:

public void MyCommandExecute(对象参数) { 这个.mainWindowModel.MyAction(); }

在xaml中,必须将DataContext设置为:

<Window.DataContext>
   <viewModel:MainWindowViewModel/>
</Window.DataContext>
现在,您可以将button命令绑定到ViewModel的ICommand属性,如下所示:

class MainWindowViewModel
{
   private readonly MainWindowModel mainWindowModel;

   public MainWindowViewModel()
   {
      this.mainWindowModel = new MainWindowModel();
   }

在您的模型中,您有自己的功能:

class MainWindowModel
{
   public void MyAction()
   {...}
}
在ViewModel的构造函数中,创建模型的实例,如:

class MainWindowViewModel
{
   private readonly MainWindowModel mainWindowModel;

   public MainWindowViewModel()
   {
      this.mainWindowModel = new MainWindowModel();
   }
然后您就有了一个
ICommand
的实现,比如RelayCommand:

public class ViewModel
{
    public ViewModel()
    {
        this.ButtonClick = new RelayCommand(_ => this.DoSomething());
    }

    public ICommand ButtonClick { get; set; }

    public void DoSomething()
    {
        // Something...
    }
}
public class RelayCommand : ICommand
    {
        private readonly Action<object> execute;
        private readonly Predicate<object> canExecute;

        public RelayCommand(Action<object> exectue, Predicate<object> canExecute = null)
        {
            if (exectue == null)
                throw new ArgumentNullException("exectue");
            this.execute = exectue;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return this.canExecute == null || this.canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            this.execute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }
当您实现
INotifyPropertyChanged
-接口时,得到的OnPropertyChanged事件

 public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
在ViewModel的构造函数中实例化MyCommand,如

this.MyCommand = new RelayCommand(MyCommandExecute);
然后必须在viewmodel中创建一个方法,在其中调用模型的MyAction方法:

public void MyCommandExecute(对象参数) { 这个.mainWindowModel.MyAction(); }

在xaml中,必须将DataContext设置为:

<Window.DataContext>
   <viewModel:MainWindowViewModel/>
</Window.DataContext>
现在,您可以将button命令绑定到ViewModel的ICommand属性,如下所示:

class MainWindowViewModel
{
   private readonly MainWindowModel mainWindowModel;

   public MainWindowViewModel()
   {
      this.mainWindowModel = new MainWindowModel();
   }

我知道数据上下文,但从未听说过ViewModelLocator,也从未听说过依赖项注入。。。在您的代码中,ExecuteAction方法用于什么?您使用它来定义命令吗?ExecuteAction是您调用模型操作的地方。这样,ViewModel将从视图中隐藏模型。互联网上有很多关于VIEVMODELLOCATOR和依赖注入的信息。下载MVVM Light Toolkit,例如,在那里,您可以在一个很好的工具包中阅读所有这些东西,其中包含源代码。我知道数据上下文,但从未听说过ViewModelLocator,也没有听说过依赖项注入。。。在您的代码中,ExecuteAction方法用于什么?您使用它来定义命令吗?ExecuteAction是您调用模型操作的地方。这样,ViewModel将从视图中隐藏模型。互联网上有很多关于VIEVMODELLOCATOR和依赖注入的信息。下载MVVM Light Toolkit,例如,在那里,您可以在一个很好的工具包中找到所有这些东西,并提供源代码供您阅读。