Mvvm Light Toolkit for wpfsilverlight系列之Command和Events

Mvvm Light Toolkit for wpfsilverlight系列之Command和Events,第1张

概述事件是WPF/SL应用程序中UI与后台代码进行交互的最主要方式,与传统方式不同,mvvm中主要通过绑定到命令来进行事件的处理,因此要了解mvvm中处理事件的方式,就必须先熟悉命令的工作原理。    一、RelayCommand命令 WPF/SL命令是通过实现 ICommand 接口创建的。 ICommand 公开两个方法(Execute 及 CanExecute)和一个事件(CanExecuteC

事件是WPF/SL应用程序中UI与后台代码进行交互的最主要方式,与传统方式不同,mvvm中主要通过绑定到命令来进行事件的处理,因此要了解mvvm中处理事件的方式,就必须先熟悉命令的工作原理。 

 

一、RelayCommand命令

WPF/SL命令是通过实现 ICommand 接口创建的。 ICommand 公开两个方法(Execute 及 CanExecute)和一个事件(CanExecuteChanged)。Execute 执行与命令关联的 *** 作。CanExecute 确定是否可以在当前命令目标上执行命令。在Mvvmlight中实现ICommand接口的类是RelayCommand,RelayCommand通过构造函数初始化Execute 和 CanExecute方法,因此,构造函数传入的是委托类型的参数,CanExecute则执行的是委托的方法,RelayCommand相关代码如下:

[c-sharp]  view plain copy public RelayCommand(Action execute, Func<bool> canExecute)   {       if (execute == null)       {           throw new ArgumentNullException("execute");       }          _execute = execute;       _canExecute = canExecute;   }   [DeBUGgerStepThrough]   public bool CanExecute(object parameter)   return _canExecute == null ? true : _canExecute();   voID Execute(object parameter)   {       _execute();   }  

 

二、 Comand属性绑定

通常实现了 ICommandSource的控件可以使用Comand属性绑定,实现 ICommandSource 的 WPF 类包括:ButtonBase、MenuItem、Hyperlink 以及InputBinding。

简单绑定示例:

xaml:

[xhtml]  copy <button Command="{Binding SimpleCommand}" Content="简单命令" />    

viewmodel:

copy public Mainviewmodel()        ...             SimpleCommand = new RelayCommand           (               () => CommandResult = "执行简单命令"           );  

注意:SL4才开始支持Command属性绑定,之前的版本不能使用Command属性绑定

CanExecute命令绑定示例:

xaml:

 

copy button Command="{Binding CanExecuteCommand}" Content="CanExecute命令" margin="5,5,0"/>   CheckBox x:name="chkCanClick" IsChecked="{Binding CanClick,Mode=TwoWay}"              Content="勾上复选框,CanExecute命令按钮才能变为可用"/>  

viewmodel:

copy bool _CanClick;   bool CanClick       get { return _CanClick; }   set       {           if (_CanClick == value)               return;           _CanClick = value;           RaisePropertyChanged("CanClick");                      // SL中需要手动调用RaiseCanExecuteChanged方法更新按钮可用s状态           CanExecuteCommand.RaiseCanExecuteChanged();   }       ...       CanExecuteCommand =         (              () =>              {                  CommandResult = "执行CanExecute命令";              },              () => CanClick  // 等价于()=>{return CanClick;}          );          ...   }  

与简单命令绑定不同的是,CanExecuteCommand构造函数包含两个参数,第二个参数的返回值表示是否可以在按钮上执行命令 *** 作,返回False,则不能在按钮上执行命令,因此按钮为不可用,返回True,则能够在按钮上执行命令,按钮可用。以上示例中,CanExecute返回值与CheckBox的IsChecked属性关联,这样更改CheckBox的勾选状态,按钮的可用状态会随之更改。

 

带参数的命令绑定示例:

xaml:

copy button
 Command="{Binding ParamCommand}" Content="带参数的CanExecute命令"  
        CommandParameter="{Binding CanClick,Mode=OneWay}" margin="5,0); background-color:inherit; Font-weight:bold">/>  

viewmodel:

copy      ParamCommand = new RelayCommand<bool?>               (p) =>               {                   CommandResult = string.Format("执行带参数的命令(参数值:{0})", p);               },108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px">             (p) => p??false           );   }  

这里ParamCommand接收TextBox的值作为参数,泛型版本表示参数类型为string,此时Execute和CanExecute参数也必须是带参数的版本。

 

注意:

   1、在SL4中带参数的CanExecute与不带参数的CanExecute之间的区别;带参数的CanExecute,与参数绑定的属性(CanClick)更改,会自动触发命令的CanExecute方法,而不带参数的CanExecute方法,则需要手动调用CanExecuteCommand.RaiseCanExecuteChanged()方法更新按钮的可用状态。

 2、在WPF中,RelayCommand通过CommandManager不停地侦听按钮的CanExecute的状态,因此WPF中按钮的CanExecute状态会随时响应CanExecute方法中的更改,WPF中可以不调用命令的RaiseCanExecuteChanged方法

 

      三、使用行为绑定命令

Command属性绑定只能绑定ICommandSource类型的控件的点击事件,对于其他控件事件,比如TextChanged事件,不能直接绑定到Command,这时我们可以使用Blend的InvokeCommandAction行为来绑定事件到命令,使用步骤如下:

用Blend4打开解决方案,选中要触发事件的控件,比如TextBox,在资产面板中选择行为,在列表中选择InvokeCommandAction,如图:

 

 双击InvokeCommandAction后会为TextBox生成InvokeCommandAction行为,在属性栏可以设置行为的属性:

在Eventname栏选择触发的事件名称TextChanged,Command绑定跟button的绑定方式一样,最后我们生成的代码如下:

xaml:

 

copy TextBox
 x:name="TextBox1" margin="5,0" WIDth="100">     i:Interaction.Triggers>       i:EventTrigger Eventname="TextChanged"       i:InvokeCommandAction Command="{Binding BehavIoUrCommand, Mode=OneWay}"                                CommandParameter="{Binding Text,Elementname=TextBox1}"     </i:EventTrigger   TextBox>  

viewmodel:

copy     BehavIoUrCommand = string>              (p) =>                  CommandResult = string.Format("执行TextChanged命令,触发命令的TextBox值为{0}",p);              (p) =>               {                   return !string.IsNullOrEmpty(p);               }          );       ...   }  

这样就可以间接的将TextBox的MouseRightbuttonDown事件绑定到Command。

这种方式相当于将事件映射到Command,CanExecute的返回值只能决定命令是否会被执行,而不能是使得命令目标的可用状态发生改变。以上示例中,输入第一个字母时,命令并没有执行,此时命令无效,但文本框仍然有效,输入第二个字母命令才执行

 

四、使用Mvvmlight行为EventToCommand绑定命令

虽然InvokeCommandAction行为可以将控件的事件转换到Command绑定,也可以通过CommandParameter向viewmodel传递参数,但是对于一些特殊的事件,比如MouseMove,我们需要在事件处理方法中得到鼠标位置信息,使用上面的方式仍不能完成任务;这时我们就需要使用EventToCommand行为,它是Mvvmlight封装的行为,要使用行为需要添加galaSoft.Mvvmlight.Extras.dll和System.windows.Interactivity.dll的引用。

同样,在Blend4中打开解决方案,选中要触发事件的控件 ,在资产面板中选择行为,在列表中选择EventToCommand,双击生成行为,然后设置Eventname为MouseMove,然后设置Command绑定,同时需要设置PassEventArgsToCommand="True",也就是将事件参数传递给Command,生成的代码如下:

xaml:

copy GrID
        Ellipse Fill="AliceBlue" Height="180" stroke="Black" margin="10,8"                    i:EventTrigger Eventname="MouseMove"             galaSoft_Mvvmlight_Command:EventToCommand PassEventArgsToCommand="True"                                               Command="{Binding MoveMouseCommand}" />                    EllipseTextBlock HorizontalAlignment="Center" Text="带事件参数的命令 (鼠标移动事件)"                    textwrapPing="Wrap" GrID.Row="7" d:LayoutOverrIDes="Height"                    GrID.ColumnSpan="2" VerticalAlignment="Center"                    FontSize="20" FontWeight="Bold"                    IsHitTestVisible="False" >  

viewmodel:

copy MoveMouseCommand = new RelayCommand<MouseEventArgs>       (           (e) =>                    var element = e.OriginalSource as UIElement;                   var point = e.Getposition(element);                   CommandResult = string.Format("执行带MouseEventArgs事件参数的命令,鼠标位置:X-{0},Y-{1}",point.X,point.Y);               }       );  

这里命令的初始化方式与带参数的命令一样,只需将参数类型换成事件参数类型

 

EventToCommand不仅可以用来传递事件参数,他还可以将CanExecute返回值与命令目标的IsEnable属性关联,我们只需将MustToggleIsEnabled的属性设置为True就可以了,示例代码如下:

xaml:

copy TextBox
 x:name="TextBox2" Text="为空时CanExecute为false" margin="5,0" WIDth="200"             galaSoft_Mvvmlight_Command:EventToCommand Command="{Binding BehavIoUrCommand}"                                                          MustToggleIsEnabled="{Binding IsChecked,Elementname=chkMustToggle}"                                                            CommandParameter="{Binding Text,Elementname=TextBox2}" CheckBox x:name="chkMustToggle" IsChecked="False" Content="MustToggleIsEnabled,勾选则TextBox的可用状态与CanExecute返回值关联"/>  

 

五、使用自定义行为绑定命令

如果以上方法都不能满足你的要求,你还可以自定义行为来绑定命令,以下是WPF中自定义行为的代码(SL代码请在文章最后下载示例代码对照阅读):

首先,我们创建一个命令参数类型:

copy using
 System;  
using
 System.windows;  
namespace
 MvvmlightCommand.WPF4.TriggerActions  
class
 Eventinformation<TEventArgsType>  
object
 Sender { getset; }  
public
 TEventArgsType EventArgs { set; }  
object
 CommandArgument {      }   }  

然后创建行为类:

copy using
 System.windows.Interactivity;  
using System.windows.input;   namespace MvvmlightCommand.WPF4.TriggerActions   class MapEventToCommand : MapEventToCommandBase<EventArgs>   class MapRoutedEventToCommand : MapEventToCommandBase<RoutedEventArgs>   abstract class MapEventToCommandBase<TEventArgsType> : TriggerAction<FrameworkElement>           where TEventArgsType : EventArgs   static Readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command"typeof(ICommand),153); background-color:inherit; Font-weight:bold">typeof(MapEventToCommandBase<TEventArgsType>),153); background-color:inherit; Font-weight:bold">new PropertyMetadata(null, OnCommandPropertyChanged));   Readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter",153); background-color:inherit; Font-weight:bold">typeof(object), OnCommandParameterPropertyChanged));   private voID OnCommandParameterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)           {               var invokeCommand = d as MapEventToCommand;               if (invokeCommand != null)               {                   invokeCommand.SetValue(CommandParameterProperty, e.NewValue);           }   voID OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)           {               var invokeCommand = d as MapEventToCommand;                   invokeCommand.SetValue(CommandProperty, e.NewValue);               }           }   protected overrIDe voID Invoke(if (this.Command ==                               var eventInfo = new Eventinformation<TEventArgsType>                   EventArgs = parameter as TEventArgsType,                   Sender = this.Associatedobject,                   CommandArgument = GetValue(CommandParameterProperty)               };   this.Command.CanExecute(eventInfo))   this.Command.Execute(eventInfo);   public ICommand Command   get   return (ICommand)base.GetValue(CommandProperty);   set   base.SetValue(CommandProperty, value);   object CommandParameter   return base.GetValue(CommandParameterProperty);   base.SetValue(CommandParameterProperty,248); line-height:18px"> }  

编译生成项目,在Blend4中打开解决方案,选中要触发事件的控件 ,在资产面板中选择行为,在列表中选择MapRoutedEventToCommand ,双击生成行为,然后设置Eventname为TextChanged,然后设置Command绑定,代码如下:

xaml:

copy TextBox
 x:name="TextBox3" Text="更改文本框的值" margin="5,0); background-color:inherit; Font-weight:bold">my:MapRoutedEventToCommand Command="{Binding CustomBehaviorCommand}" CommandParameter="P1"copy CustomBehaviorCommand = new RelayCommand<Eventinformation<RoutedEventArgs>>      (          (ei) =>          {              Eventinformation<RoutedEventArgs> eventInfo = ei as Eventinformation<RoutedEventArgs>;              System.windows.Controls.TextBox sender = eventInfo.Sender as System.windows.Controls.TextBox;              CommandResult = string.Format("执行{0}的TextChanged命令,文本框的值:{1},传递的参数:{2},事件参数:{3}",248); line-height:18px">                sender.name,108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px">                sender.Text,                  ei.CommandArgument,108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px">                ei.EventArgs.GetType().ToString());          },108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px">            true;          }      );  

这样,我们就可以同时将sender、CommandParameter、和事件参数传递到Command的参数中了

 

本章节主要介绍Mvvmlight中命令和事件的处理方法,下章我们将介绍Mvvmlight中的Messenger的使用方法,以下是本章源代码下载:

 

http://download.csdn.net/source/3262832

总结

以上是内存溢出为你收集整理的Mvvm Light Toolkit for wpf/silverlight系列之Command和Events全部内容,希望文章能够帮你解决Mvvm Light Toolkit for wpf/silverlight系列之Command和Events所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1019115.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-23
下一篇2022-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存