你的位置:首页 > ASP.net教程

[ASP.net教程]WPF学习08:MVVM 预备知识之COMMAND


    WPF内建的COMMAND是GOF 提出的23种设计模式中,命令模式的实现。

    本文是WPF学习07:MVVM 预备知识之数据绑定的后续,将说明实现COMMAND的三个重点:ICommand  CommandManager InputBindings

 

COMMAND简介

    一般情况我们应用设计如下,一个个控件的各类Handler直接关心了如何实现具体的应用逻辑。

    image

    借助COMMAND,我们将具体实现的应用逻辑放在COMMAND中实现,控件只需要绑定相应的COMMAND,而无需关心应用逻辑,从而实现界面与应用逻辑的解耦。

    image

    WPF内建的COMMAND除了提供了逻辑解耦外,还可以用来实现控件使能管理、命令的历史记录(使操作可撤销)。

    本文将介绍如何在MVVM下运用COMMAND,以及控件的使能管理。历史记录功能将在下篇学习笔记中再介绍。


 

例子

    由CheckBox 管理Command是否可以被执行,Ctrl + A与按键被按均能执行同样的业务逻辑。

    imageimageimage

    XAML代码:

<Window x:Class="Commands.CommandBlog"    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    ="http://schemas.microsoft.com/winfx/2006/xaml"    Title="CommandBlog" Height="300" Width="300">  <Window.InputBindings>    <KeyBinding Key="A" Modifiers="Control" Command="{Binding NewFile}"></KeyBinding>  </Window.InputBindings>  <StackPanel Background="White">    <Button Command="{Binding NewFile}">New file</Button>    <CheckBox IsChecked="{Binding NewFileEnable}" HorizontalAlignment="Center">New file Function Enable</CheckBox>  </StackPanel></Window>

 

    界面部分后台代码,只需要配置DataContext即可:

public partial class CommandBlog : Window{  public CommandBlog()  {    InitializeComponent();    DataContext = new CommandBlogViewModel();  }}

 

    CommandBlogViewModel:

class CommandBlogViewModel:INotifyPropertyChanged{  public event PropertyChangedEventHandler PropertyChanged;  public ICommand NewFile  {    get;    private set;  }  public CommandBlogViewModel()  {    NewFile = new NewFileCommand(this);  }  private Boolean newFileEnable;  public Boolean NewFileEnable  {    get { return newFileEnable; }    set     {       newFileEnable = value;      if (PropertyChanged != null)        PropertyChanged.Invoke(this, new PropertyChangedEventArgs("NewFileEnable"));    }  }}

 

    NewFileCommand:

class NewFileCommand : ICommand{  private CommandBlogViewModel commandBlogViewModel;  public NewFileCommand(CommandBlogViewModel commandBlogViewModel)  {    this.commandBlogViewModel = commandBlogViewModel;  }  public bool CanExecute(object parameter)  {    return this.commandBlogViewModel.NewFileEnable;  }  public event EventHandler CanExecuteChanged  {    add { CommandManager.RequerySuggested += value; }    remove { CommandManager.RequerySuggested -= value; }  }  public void Execute(object parameter)  {    MessageBox.Show("New");  }}


 

ICommand 

// Summary://   Occurs when changes occur that affect whether or not the command should execute.event EventHandler CanExecuteChanged;// Summary://   Defines the method that determines whether the command can execute in its//   current state.bool CanExecute(object parameter);// Summary://   Defines the method to be called when the command is invoked.void Execute(object parameter);

    CanExecute与Execute的意思都很明显,可以在刚才的例子中看出来。这里重点介绍一下如何给它们传参。

    我们可以通过设置CommandParameter向两者传参:
    例子:

<!--主窗体起名为MainWindow--><Button Command="{Binding NewFile}" CommandParameter="{Binding ElementName=MainWindow}">New file</Button>

   
public void Execute(object parameter){  var inputElement = parameter as IInputElement;  if (inputElement!= null)  {    var pos = Mouse.GetPosition(inputElement);  }}

   


 

CommandManager

    为了使WPF能够自动识别CanExecute的变化,我们需要手动对CanExecuteChanged加以下代码:   

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


 

InputBindings

    当我们希望可以自定义命令的输入映射时,需要用到InputBindings:

    例子:

<Window.InputBindings>  <KeyBinding Key="A" Modifiers="Control" Command="{Binding NewFile}"></KeyBinding>  <KeyBinding Key="C" Modifiers="Control" Command="{Binding CopyContent}"></KeyBinding>  <KeyBinding Key="V" Modifiers="Control" Command="{Binding PasteContent}"></KeyBinding>  <KeyBinding Key="F1" Modifiers="Control" Command="{Binding HelpPrompt}"></KeyBinding></Window.InputBindings>