分享

MVVM中轻松实现Command绑定(五)获取事件参数EventArgs(2)

 TT_TYG 2013-04-28

MVVM中轻松实现Command绑定(五)获取事件参数EventArgs(2)

分类: C# WPF Command EventArgs ViewModel MVVM 4375人阅读 评论(9) 收藏 举报

在上一节中我介绍了“MVVM中轻松实现Command绑定(四)获取事件参数EventArgs”,通过Loaded事件传递控件对象,然后添加事件方法,这样做是可以的,但是不符合MVVM的思想,今日我介绍另一种方法,通过扩展interactivity的InvokeCommandAction来实现事件参数传递。

先来看普通的InvokeCommandAction方式

  1. <Window x:Class="EventArgsInViewModel.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"  
  5.         xmlns:loc="clr-namespace:EventArgsInViewModel"  
  6.         Title="MainWindow" Height="350" Width="525">  
  7.     <Window.DataContext>  
  8.         <loc:MainWindowViewModel />  
  9.     </Window.DataContext>  
  10.     <Grid>  
  11.         <Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="50,52,0,0" Name="button1" VerticalAlignment="Top" Width="138">  
  12.             <i:Interaction.Triggers>  
  13.                 <i:EventTrigger EventName="Click">  
  14.                     <i:InvokeCommandAction   
  15.                         Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=button1}" />  
  16.                 </i:EventTrigger>  
  17.             </i:Interaction.Triggers>  
  18.         </Button>  
  19.     </Grid>  
  20. </Window>  

现在为了扩展CommandParameter,定义ExCommandParameter类

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Windows;  
  6.   
  7. namespace EventArgsInViewModel {  
  8.     /// <summary>  
  9.     /// 扩展CommandParameter,使CommandParameter可以带事件参数  
  10.     /// </summary>  
  11.     public class ExCommandParameter {  
  12.         /// <summary>  
  13.         /// 事件触发源  
  14.         /// </summary>  
  15.         public DependencyObject Sender { getset; }  
  16.         /// <summary>  
  17.         /// 事件参数  
  18.         /// </summary>  
  19.         public EventArgs EventArgs { getset; }  
  20.         /// <summary>  
  21.         /// 额外参数  
  22.         /// </summary>  
  23.         public object Parameter { getset; }  
  24.     }  
  25. }  


然后定义ExInvokeCommandAction类,用于扩展InvokeCommandAction

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Windows;  
  6. using System.Windows.Interactivity;  
  7. using System.Windows.Input;  
  8. using System.Reflection;  
  9.   
  10. namespace EventArgsInViewModel {  
  11.     /// <summary>  
  12.     /// 扩展的InvokeCommandAction  
  13.     /// </summary>  
  14.     public class ExInvokeCommandAction : TriggerAction<DependencyObject> {  
  15.   
  16.         private string commandName;  
  17.         public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command"typeof(ICommand), typeof(ExInvokeCommandAction), null);  
  18.         public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter"typeof(object), typeof(ExInvokeCommandAction), null);  
  19.         /// <summary>  
  20.         /// 获得或设置此操作应调用的命令的名称。  
  21.         /// </summary>  
  22.         /// <value>此操作应调用的命令的名称。</value>  
  23.         /// <remarks>如果设置了此属性和 Command 属性,则此属性将被后者所取代。</remarks>  
  24.         public string CommandName {  
  25.             get {  
  26.                 base.ReadPreamble();  
  27.                 return this.commandName;  
  28.             }  
  29.             set {  
  30.                 if (this.CommandName != value) {  
  31.                     base.WritePreamble();  
  32.                     this.commandName = value;  
  33.                     base.WritePostscript();  
  34.                 }  
  35.             }  
  36.         }  
  37.         /// <summary>  
  38.         /// 获取或设置此操作应调用的命令。这是依赖属性。  
  39.         /// </summary>  
  40.         /// <value>要执行的命令。</value>  
  41.         /// <remarks>如果设置了此属性和 CommandName 属性,则此属性将优先于后者。</remarks>  
  42.         public ICommand Command {  
  43.             get {  
  44.                 return (ICommand)base.GetValue(ExInvokeCommandAction.CommandProperty);  
  45.             }  
  46.             set {  
  47.                 base.SetValue(ExInvokeCommandAction.CommandProperty, value);  
  48.             }  
  49.         }  
  50.         /// <summary>  
  51.         /// 获得或设置命令参数。这是依赖属性。  
  52.         /// </summary>  
  53.         /// <value>命令参数。</value>  
  54.         /// <remarks>这是传递给 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks>  
  55.         public object CommandParameter {  
  56.             get {  
  57.                 return base.GetValue(ExInvokeCommandAction.CommandParameterProperty);  
  58.             }  
  59.             set {  
  60.                 base.SetValue(ExInvokeCommandAction.CommandParameterProperty, value);  
  61.             }  
  62.         }  
  63.         /// <summary>  
  64.         /// 调用操作。  
  65.         /// </summary>  
  66.         /// <param name="parameter">操作的参数。如果操作不需要参数,则可以将参数设置为空引用。</param>  
  67.         protected override void Invoke(object parameter) {  
  68.             if (base.AssociatedObject != null) {  
  69.                 ICommand command = this.ResolveCommand();  
  70.   
  71.                 /* 
  72.                  * ★★★★★★★★★★★★★★★★★★★★★★★★ 
  73.                  * 注意这里添加了事件触发源和事件参数 
  74.                  * ★★★★★★★★★★★★★★★★★★★★★★★★ 
  75.                  */  
  76.                 ExCommandParameter exParameter = new ExCommandParameter {  
  77.                     Sender=base.AssociatedObject,  
  78.                     Parameter = GetValue(CommandParameterProperty),  
  79.                     EventArgs=parameter as EventArgs  
  80.   
  81.                 };  
  82.                   
  83.                 if (command != null && command.CanExecute(exParameter)) {  
  84.                     /* 
  85.                      * ★★★★★★★★★★★★★★★★★★★★★★★★ 
  86.                      * 注意将扩展的参数传递到Execute方法中 
  87.                      * ★★★★★★★★★★★★★★★★★★★★★★★★ 
  88.                      */  
  89.                     command.Execute(exParameter);  
  90.                 }  
  91.             }  
  92.         }  
  93.         private ICommand ResolveCommand() {  
  94.             ICommand result = null;  
  95.             if (this.Command != null) {  
  96.                 result = this.Command;  
  97.             } else {  
  98.                 if (base.AssociatedObject != null) {  
  99.                     Type type = base.AssociatedObject.GetType();  
  100.                     PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);  
  101.                     PropertyInfo[] array = properties;  
  102.                     for (int i = 0; i < array.Length; i++) {  
  103.                         PropertyInfo propertyInfo = array[i];  
  104.                         if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType) && string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal)) {  
  105.                             result = (ICommand)propertyInfo.GetValue(base.AssociatedObject, null);  
  106.                         }  
  107.                     }  
  108.                 }  
  109.             }  
  110.             return result;  
  111.         }  
  112.   
  113.     }  
  114. }  


好了,我们把xaml改一下,现在改用我们自己创建的ExInvokeCommandAction

  1. <Window x:Class="EventArgsInViewModel.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"  
  5.         xmlns:loc="clr-namespace:EventArgsInViewModel"  
  6.         Title="MainWindow" Height="350" Width="525">  
  7.     <Window.DataContext>  
  8.         <loc:MainWindowViewModel />  
  9.     </Window.DataContext>  
  10.     <Grid>  
  11.         <Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="50,52,0,0" Name="button1" VerticalAlignment="Top" Width="138">  
  12.             <i:Interaction.Triggers>  
  13.                 <i:EventTrigger EventName="Click">  
  14.                     <!--★★★扩展的InvokeCommandAction★★★-->  
  15.                     <loc:ExInvokeCommandAction   
  16.                         Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=button1}" />  
  17.                 </i:EventTrigger>  
  18.             </i:Interaction.Triggers>  
  19.         </Button>  
  20.     </Grid>  
  21. </Window>  

ViewModel代码

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Windows.Input;  
  6. using Microsoft.Practices.Prism.Commands;  
  7. using System.Windows;  
  8.   
  9. namespace EventArgsInViewModel {  
  10.     public class MainWindowViewModel {  
  11.         public ICommand ClickCommand {  
  12.             get {  
  13.                 return new DelegateCommand<ExCommandParameter>((p) => {  
  14.                     RoutedEventArgs args = p.EventArgs as RoutedEventArgs;  
  15.                     MessageBox.Show(args.ToString());  
  16.                 },  
  17.                 (p) => {  
  18.                     return true;  
  19.                 }  
  20.                 );  
  21.             }  
  22.         }  
  23.     }  
  24. }  



现在点击一下按钮,显示了对应的消息框,OK,参数也能得到。是不是也很容易啊。
那么有人问,除了ExInvokeCommandAction我也会,但是ExInvokeCommandAction让人想破脑袋也不会写。其实,我也不会写,我只是用ILSpy反编译了一下,然后稍稍改动而已(这个我还是可以做到的)。
最后我想说:“其实你只要动脑筋都做到的事很多!”

下载地址:http://qing2005.download.csdn.net/

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多