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