在MVVM架构下,把EventArgs绑定到Command上【翻译】

  在使用MVVM架构时,我们会遇到各种各样的问题

  其中一个很常见的问题就是如何在ViewModel层处理UI事件时在后台代码文件中不写任何代码。

  在我这个例子中实现的是取得鼠标移动时的位置。

  我的解决方法如下:

  1、通过一个Behavior 取得关联对象的EventArgs,代码如下

 1  public   class  ExtendedInvokeCommandAction : TriggerAction < FrameworkElement >
 2      {
 3           public   static   readonly  DependencyProperty CommandProperty  =  DependencyProperty.Register( " Command " typeof (ICommand),  typeof (ExtendedInvokeCommandAction),  new  PropertyMetadata( null , CommandChangedCallback));
 4           public   static   readonly  DependencyProperty CommandParameterProperty  =  DependencyProperty.Register( " CommandParameter " typeof ( object ),  typeof (ExtendedInvokeCommandAction),  new  PropertyMetadata( null , CommandParameterChangedCallback));
 5 
 6           private   static   void  CommandParameterChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
 7          {
 8              var invokeCommand  =  d  as  ExtendedInvokeCommandAction;
 9               if  (invokeCommand  !=   null )
10                  invokeCommand.SetValue(CommandParameterProperty, e.NewValue);
11          }
12 
13           private   static   void  CommandChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
14          {
15              var invokeCommand  =  d  as  ExtendedInvokeCommandAction;
16               if  (invokeCommand  !=   null )
17                  invokeCommand.SetValue(CommandProperty, e.NewValue);
18          }
19 
20           protected   override   void  Invoke( object  parameter)
21          {
22               if  ( this .Command  ==   null )
23                   return ;
24 
25               if  ( this .Command.CanExecute(parameter))
26              {
27                  var commandParameter  =   new  ExtendedCommandParameter(parameter  as  EventArgs,  this .AssociatedObject,
28                                                                      GetValue(CommandParameterProperty));
29                   this .Command.Execute(commandParameter);
30              }
31          }
32 
33           #region  public properties
34 
35           public   object  CommandParameter
36          {
37               get  {  return  GetValue(CommandParameterProperty); }
38               set  { SetValue(CommandParameterProperty, value); }
39          }
40 
41           public  ICommand Command
42          {
43               get  {  return  GetValue(CommandProperty)  as  ICommand; }
44               set  { SetValue(CommandParameterProperty, value); }
45          }
46 
47           #endregion
48      }

 

  2、写一个类,包含的属性有事件源、EventArgs和对象,代码如下

 1  public   class  ExtendedCommandParameter
 2      {
 3           public  ExtendedCommandParameter(EventArgs eventArgs, FrameworkElement sender,  object  parameter)
 4          {
 5              EventArgs  =  eventArgs;
 6              Sender  =  sender;
 7              Parameter  =  parameter;
 8          }
 9 
10           public  EventArgs EventArgs {  get private   set ; }
11           public  FrameworkElement Sender {  get private   set ; }
12           public   object  Parameter {  get private   set ; }
13      }

 

  3、为对象添加Behavior

  在我的这个例子中,我对Rectangle添加新建的类ExtendedInvokeCommandAction(即Behavior)

  4、在ViewModel层把这个Behavior绑定到Command上,在这Command上选择一个事件,通过Comman调用这个事件

  在我这个例子中,在ViewModle层我把MouseMove事件绑定到MouseMoved Command上,另外,如果需要的话,可以把任何对象绑定到CommandParameter,在我这个例子中,我把此View(变量名为userControl)绑定到了CommandParameter(不是必须的)

  

 1 
 2  < Rectangle Fill = " #FF9B9BC5 "  Height = " 200 "  Stroke = " Black "  Width = " 200 " >
 3               < i:Interaction.Triggers >
 4                   < i:EventTrigger EventName = " MouseMove " >
 5                       < local:ExtendedInvokeCommandAction
 6                      Command = " {Binding MouseMoved} "
 7                      CommandParameter = " {Binding ElementName=userControl} " />
 8                   </ i:EventTrigger >
 9               </ i:Interaction.Triggers >
10           </ Rectangle >
11 

 

  5、在ViewModel层处理事件,代码如下

 

 1  public   class  MainPageViewModel : INotifyPropertyChanged
 2      {
 3           public  MainPageViewModel()
 4          {
 5              MouseMoved  =   new  MainPageCommand( this );  // initialize the Command
 6          }
 7 
 8           // gets the position of the mouse
 9           private   void  OnMouseMove(ExtendedCommandParameter commandParameter)
10          {
11              MouseEventArgs eventArgs;
12 
13               // cast the EventArgs to the type you expect, according to the event you handle
14               // f.e. MouseMove Event  gets you MouseEventArgs
15               //      Click Event gets you RoutedEventArgs
16               if  (commandParameter.EventArgs.GetType()  ==   typeof (MouseEventArgs))
17              {
18                  eventArgs  =  commandParameter.EventArgs  as  MouseEventArgs;
19                   if  (commandParameter.Parameter  !=   null )
20                  {
21                      var view  =  commandParameter.Parameter  as  UIElement;
22                      MousePosition  =  eventArgs.GetPosition(view).ToString();
23                  }
24              }
25          }
26 
27           public  MainPageCommand MouseMoved {  get set ; }
28           private   string  _mousePosition;
29           public   string  MousePosition
30          {
31               get  {  return  _mousePosition; }
32               set  { _mousePosition  =  value; OnPropertyChanged( " MousePosition " ); }
33          }
34 
35           #region  INotifyChanged Members
36 
37           public   event  PropertyChangedEventHandler PropertyChanged;
38           internal   void  OnPropertyChanged( string  propertyName)
39          {
40               if  ( this .PropertyChanged  !=   null )
41              {
42                   this .PropertyChanged( this new  PropertyChangedEventArgs(propertyName));
43              }
44          }
45 
46           #endregion
47 
48           #region  command class
49 
50           public   class  MainPageCommand : ICommand
51          {
52               public  MainPageCommand(MainPageViewModel view)
53              {
54                  _view  =  view;
55              }
56 
57               private  MainPageViewModel _view;
58 
59               #region  ICommand Members
60 
61               public   bool  CanExecute( object  parameter)
62              {
63                   return   true ;
64              }
65 
66               public   event  EventHandler CanExecuteChanged;
67 
68               public   void  Execute( object  parameter)
69              {
70                   // call the method to handle the event
71                  _view.OnMouseMove(parameter  as  ExtendedCommandParameter);
72              }
73 
74               #endregion
75 
76          }
77       #endregion
78 
79      }

  如果需要,可以为每一个EventArgs建一个Behavior,只要把它绑定到Command上,然后Command代码中处理EventArgs就可以了

  代码下载

  另外还有一篇英文的文章,和这篇文章差不多,但是写的更好,而且程序写的也很好,如果有兴趣的话,也看一下。文章地址为http://blog.roboblob.com/2010/01/26/binding-ui-events-from-view-to-commands-in-viewmodel-in-silverlight-4/

转载于:https://www.cnblogs.com/888h/archive/2010/12/18/1910167.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在MVVM模式下将PasswordBox的密码绑定到ViewModel,可以使用PasswordBox的Password属性和CommandBinding来实现。 首先,在XAML中给PasswordBox绑定一个CommandBinding,如下所示: ``` <PasswordBox Password="{Binding Password}" > <i:Interaction.Triggers> <i:EventTrigger EventName="PasswordChanged"> <i:InvokeCommandAction Command="{Binding PasswordChangedCommand}" /> </i:EventTrigger> </i:Interaction.Triggers> </PasswordBox> ``` 这里使用了System.Windows.Interactivity命名空间中的Interactivity和EventTrigger,需要在XAML中引用: ``` xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" ``` 然后,在ViewModel中定义Password属性和PasswordChangedCommand命令,如下所示: ``` public class ViewModel : INotifyPropertyChanged { private string _password; public string Password { get { return _password; } set { if (_password != value) { _password = value; OnPropertyChanged("Password"); } } } public ICommand PasswordChangedCommand { get; set; } public ViewModel() { PasswordChangedCommand = new RelayCommand<object>(OnPasswordChanged); } private void OnPasswordChanged(object obj) { Password = (obj as PasswordBox).Password; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ``` 这里使用了RelayCommand,需要在ViewModel中引用System.Windows.Input命名空间。 在PasswordChangedCommand中,通过强制类型转换获取PasswordBox的Password,然后将其赋值给ViewModel中的Password属性,实现了将PasswordBox的密码绑定到ViewModel。 注意,在PasswordChangedCommand中,要将参数类型设置为object,因为CommandParameter是object类型。 以上就是在MVVM模式下将PasswordBox的密码绑定到ViewModel的实现方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值