• mvvm 事件命令


    在使用MVVM模式时, 按照模式的规则是尽量不直接使用事件. 所以对于以前一直使用事件模式的同行来说确实有点头疼. 还好微软给我们提供了几种间接使用事件(命令)的方法, 下面我就来看看这几种方法:

    ICommand

    ICommand定义了一个接口, 使用它可以轻松的将实现ICommand的接口的命令绑定到包含命令(Command)的控件上(例如Button.Command), 在.net framework库中实现的这个接口的类不是很多, 我所知道的两个: RoutedCommand 和 RoutedUICommand, 而且这两个使用起来比较麻烦, 在这里我就不谈了, 有兴趣的同行可以研究一下. 那么, 除了上述的两个类以外还有自定义类实现ICommand和Prism的DelegateCommand. 我们先看一下自定义的;

    1. 自定义命令

    MyCommand是实现ICommand接口的一个类. 在Execute方法中我们调用传入的Action(Action包含所要实现的功能的方法), IsEnabledExecute是自定义的一个bool类型, 通过设置该值可以启用(禁用)ICommand所绑定到的控件的启用禁用状态.

    View Code
     1      public class MyCommand : ICommand
     2  
     3      {
     4  
     5          public MyCommand(Action<object> action)
     6  
     7          {
     8  
     9              if (action == null) throw new ArgumentNullException();
    10  
    11              _action = action;
    12  
    13          }
    14  
    15   
    16  
    17          private readonly Action<object> _action;
    18  
    19   
    20  
    21          private bool _isEnabledExecute = true;   //默认为启用状态
    22  
    23          public bool IsEnabledExecute
    24  
    25          {
    26  
    27              get { return _isEnabledExecute; }
    28  
    29              set
    30  
    31              {
    32  
    33                  if (_isEnabledExecute != value)
    34  
    35                  {
    36  
    37                      _isEnabledExecute = value;
    38  
    39                      if (CanExecuteChanged != null)
    40  
    41                      {
    42  
    43                          CanExecuteChanged(this, new EventArgs());
    44  
    45                      }
    46  
    47                  }
    48  
    49              }
    50  
    51          }
    52  
    53   
    54  
    55          #region ICommand 接口
    56  
    57          public event EventHandler CanExecuteChanged;
    58  
    59   
    60  
    61          public bool CanExecute(object parameter)
    62  
    63          {
    64  
    65              return _isEnabledExecute;
    66  
    67          }
    68  
    69   
    70  
    71          public void Execute(object parameter)
    72  
    73          {
    74  
    75              _action(parameter);
    76  
    77          }
    78  
    79          #endregion
    80  
    81      }

    定义好MyCommand后我们就可以使用了, 代码如下:

    View Code
     1      public class MvvmEventViewModel
     2      {
     3  
     4          public MvvmEventViewModel()
     5  
     6          {
     7  
     8              /*自定义命令*/
     9  
    10              MyCommandInstance = new MyCommand(MyCommandMethod);
    11  
    12          }
    13  
    14   
    15  
    16          /*自定义命令*/
    17  
    18          public MyCommand MyCommandInstance { get; private set; }
    19  
    20   
    21  
    22          /*Prism命令*/
    23  
    24          public DelegateCommand<object> MyDelegateCommandInstance 
    25          { get; private set; }
    26  
    27          public bool CanExecute(object parameter)
    28  
    29          {
    30  
    31              return MyDelegateCommandInstance.IsActive;
    32  
    33          }
    34  
    35   
    36  
    37          private void MyCommandMethod(object sender)
    38  
    39          {
    40  
    41              if (sender is string)
    42  
    43              {
    44  
    45                  MessageBox.Show("Hello," + sender.ToString());
    46  
    47              }
    48  
    49          }
    50  
    51      }

    <!--XAML-->

    View Code
     1 View Code 
     2 
     3             <Button Width="180"
     4 
     5                     Height="23"
     6 
     7                     Margin="0,0,7,0"
     8 
     9                     Command="{Binding MyCommandInstance}"
    10 
    11                     CommandParameter="MyCommand"
    12 
    13                     Content="MyCommand Button" />
    14 
    15             <ToggleButton Width="180"
    16 
    17                           Height="23"
    18 
    19                           Content="启用/禁用"
    20 
    21                           IsChecked="{Binding MyCommandInstance.IsEnabledExecute}" />

    首先定义了MvvmEventViewModel, 在MvvmEventViewModel中实例化了MyCommand, 将Button所在的界面或者用户控件的属性DataContext绑定上MvvmEventViewModel的实例, 最后直接在Button的Command属性上绑定MyCommandInstance;

    2.prism命令

    prism是微软的一个开源框架, 其为WPF(SL)而生, 自然也少不了MVVM模式的一些辅助类, 其中命令就是典型的辅助类. 在上面我们是自定义命令, 其实在prism框架中已经提供了命令类, 那就是DelegateCommand, 该类还为泛型提供了支持; 不仅如此prism还提供了多个命令的绑定CompositeCommand, 为一个Button命令可以执行多个方法问题提供了廉价的解决方案.

    2.1. DelegateCommand 命令

    DelegateCommand 命令与我们上面自定义的命令一样, 都是可以绑定到Button的Command属性上, 使用该类少了几行代码, 多了一份省心和安全. 如果让我选择我会选择DelegateCommand类而摒弃自定义类, 因为它可以实现我们需要的功能, 所以就没必要再重造轮子.

    View Code
     1 View Code 
     2 
     3     public class MvvmEventViewModel
     4 
     5     {
     6 
     7         public MvvmEventViewModel()
     8 
     9         {
    10 
    11             /*Prism命令*/
    12 
    13             MyDelegateCommandInstance = new DelegateCommand<object>(MyCommandMethod, CanExecute);
    14 
    15             MyDelegateCommandInstance.IsActive = true;
    16 
    17             MyDelegateCommandInstance.IsActiveChanged += (s, e) =>
    18 
    19             {
    20 
    21                 MyDelegateCommandInstance.RaiseCanExecuteChanged();
    22 
    23             };
    24 
    25         }
    26 
    27  
    28 
    29         /*Prism命令*/
    30 
    31         public DelegateCommand<object> MyDelegateCommandInstance { get; private set; }
    32 
    33         public bool CanExecute(object parameter)
    34 
    35         {
    36 
    37             return MyDelegateCommandInstance.IsActive;
    38 
    39         }
    40 
    41  
    42 
    43         private void MyCommandMethod(object sender)
    44 
    45         {
    46 
    47             if (sender is string)
    48 
    49             {
    50 
    51                 MessageBox.Show("Hello," + sender.ToString());
    52 
    53             }
    54 
    55         }
    56 
    57     }

    <!--XAML-->

    View Code
     1             <Button Width="180"
     2 
     3                     Height="23"
     4 
     5                     Margin="0,0,7,0"
     6 
     7                     Command="{Binding MyCommandInstance}"
     8 
     9                     CommandParameter="MyCommand"
    10 
    11                     Content="MyCommand Button" />
    12 
    13             <ToggleButton Width="180"
    14 
    15                           Height="23"
    16 
    17                           Content="启用/禁用"
    18 
    19                           IsChecked="{Binding MyCommandInstance.IsEnabledExecute}" />

    2.2.CompositeCommand 命令

    CompositeCommand 命令可以理解为一个命令组. 将ICommand注册到CompositeCommand中, 然后绑定在Command上, 就可以让Command触发注册到CompositeCommand的所有命令.

    2.2.1.定义一个CompositeCommand命令

    View Code
     1     public class Comm
     2 
     3     {
     4 
     5         #region CompositeCommand
     6 
     7         private static CompositeCommand _compositeCommand = new CompositeCommand();
     8 
     9         public static CompositeCommand CompositeCommand
    10 
    11         {
    12 
    13             get { return _compositeCommand; }
    14 
    15         }
    16 
    17         #endregion
    18 
    19     }

    2.2.2.使用CompositeCommand命令

    Comm.CompositeCommand.RegisterCommand(MyCommandInstance);

    Comm.CompositeCommand.RegisterCommand(MyDelegateCommandInstance);

    <!--XAML-->

    xmlns:comm="clr-namespace:Blogs.WPF"

    复制代码
    <Button Width="180"
    
                    Height="23"
    
                    Margin="0,0,7,0"
    
                    HorizontalAlignment="Left"
    
                    Command="{x:Static comm:Comm.CompositeCommand}"
    
                    CommandParameter="DelegateCommand"
    
                    Content="CompositeCommand Button" />
    复制代码

    将我们刚才定义的两个命令MyCommandInstance和MyDelegateCommandInstance注册到Comm.CompositeCommand中, 然后在一个Button上绑定 comm:Comm.CompositeCommand 此时我们单击CompositeCommand Button时发现触发了两个命令. 同样的我们也可以使用UnregisterCommand卸载命令.

    2.3.将其他事件绑定到ICommand上

    在上述的例子中我们只是在Button的Command属性上绑定ICommand, 那么对于一些特殊事件(如Loaded, MouseDown, MouseUp)我们该怎么处理呢? 网上也有一些传统的方法, 将控件直接传送到VM中, 使用+=创建特殊的事件. 其实还有更好的办法, 那就是System.Windows.Interactivity.dll 组件.

    在你的项目中引入System.Windows.Interactivity.dll, 然后在页面中添加如下代码: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

    OK, 现在就让我们就来使用这两个组件, 代码简单, 请看:

    复制代码
    public DelegateCommand LostFocusCommand { get; private set; }
     
    LostFocusCommand = new DelegateCommand(LostFocusMethod);
     
     
     
    private void LostFocusMethod()
     
    {
     
    MessageBox.Show("捕获到了.嘿牟嘿牟.");
     
    }
    复制代码
    复制代码
    <TextBlock Background="OrangeRed" Text="左键按下时我能捕获到">
     
    <i:Interaction.Triggers>
     
    <!-- 当单击鼠标左键按下时 -->
     
    <i:EventTrigger EventName="MouseLeftButtonDown">
     
    <i:InvokeCommandAction Command="{Binding LostFocusCommand}" />
     
    </i:EventTrigger>
     
    </i:Interaction.Triggers>
     
    </TextBlock>
    复制代码

    注: 名字起的有点不对应. 不想改了, 大家知道就可以.

    以上是使用System.Windows.Interactivity.dll组件可以将事件直接绑定到命令上, 但是我觉得这样麻烦, 如果可以直接使用事件岂不是更爽. 呵呵. 能提出问题就能解答问题. 我们再看另一个组件 Microsoft.Expression.Interactions.dll .

    同样的, 项目中引用 Microsoft.Expression.Interactions.dll

    添加命名空间

    复制代码
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
     
    <UserControl>
     
    <i:Interaction.Triggers>
     
    <i:EventTrigger EventName="Loaded">
     
    <ei:CallMethodAction MethodName="View_Loaded" TargetObject="{Binding}" />
     
    </i:EventTrigger>
     
    </i:Interaction.Triggers>
     
    </UserControl>
    复制代码

    注意: 在多层项目中. 只要你使用System.Windows.Interactivity.dll, Microsoft.Expression.Interactions.dll 这两个组件, 就必须在启动层中引用这两个DLL, 否则报错.

  • 相关阅读:
    函数执行的预解释
    数组的基本知识点
    前端开发概述+JS基础细节知识点
    JS数据类型的转换规则
    call,apply,求最大最小值,平均数等基础编程知识
    JS面向对象程序设计(OOP:Object Oriented Programming)
    C++ 手记
    C++ 在堆中申请内存方法
    vc驿站视频教程笔记4 Cstring 讲解
    vc驿站视频教程笔记2 ansi 和 unicode
  • 原文地址:https://www.cnblogs.com/xiaogui9527/p/2982281.html
Copyright © 2020-2023  润新知