在上一節(jié)中我介紹了“MVVM中輕松實(shí)現(xiàn)Command綁定(四)獲取事件參數(shù)EventArgs”,通過Loaded事件傳遞控件對象,然后添加事件方法,這樣做是可以的,但是不符合MVVM的思想,今日我介紹另一種方法,通過擴(kuò)展interactivity的InvokeCommandAction來實(shí)現(xiàn)事件參數(shù)傳遞。 先來看普通的InvokeCommandAction方式
<Window x:Class="EventArgsInViewModel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:loc="clr-namespace:EventArgsInViewModel" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <loc:MainWindowViewModel /> </Window.DataContext> <Grid> <Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="50,52,0,0" Name="button1" VerticalAlignment="Top" Width="138"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=button1}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Grid> </Window> 現(xiàn)在為了擴(kuò)展CommandParameter,定義ExCommandParameter類
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; namespace EventArgsInViewModel { /// <summary> /// 擴(kuò)展CommandParameter,使CommandParameter可以帶事件參數(shù) /// </summary> public class ExCommandParameter { /// <summary> /// 事件觸發(fā)源 /// </summary> public DependencyObject Sender { get; set; } /// <summary> /// 事件參數(shù) /// </summary> public EventArgs EventArgs { get; set; } /// <summary> /// 額外參數(shù) /// </summary> public object Parameter { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Interactivity; using System.Windows.Input; using System.Reflection; namespace EventArgsInViewModel { /// <summary> /// 擴(kuò)展的InvokeCommandAction /// </summary> public class ExInvokeCommandAction : TriggerAction<DependencyObject> { private string commandName; public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(ExInvokeCommandAction), null); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(ExInvokeCommandAction), null); /// <summary> /// 獲得或設(shè)置此操作應(yīng)調(diào)用的命令的名稱。 /// </summary> /// <value>此操作應(yīng)調(diào)用的命令的名稱。</value> /// <remarks>如果設(shè)置了此屬性和 Command 屬性,則此屬性將被后者所取代。</remarks> public string CommandName { get { base.ReadPreamble(); return this.commandName; } set { if (this.CommandName != value) { base.WritePreamble(); this.commandName = value; base.WritePostscript(); } } } /// <summary> /// 獲取或設(shè)置此操作應(yīng)調(diào)用的命令。這是依賴屬性。 /// </summary> /// <value>要執(zhí)行的命令。</value> /// <remarks>如果設(shè)置了此屬性和 CommandName 屬性,則此屬性將優(yōu)先于后者。</remarks> public ICommand Command { get { return (ICommand)base.GetValue(ExInvokeCommandAction.CommandProperty); } set { base.SetValue(ExInvokeCommandAction.CommandProperty, value); } } /// <summary> /// 獲得或設(shè)置命令參數(shù)。這是依賴屬性。 /// </summary> /// <value>命令參數(shù)。</value> /// <remarks>這是傳遞給 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks> public object CommandParameter { get { return base.GetValue(ExInvokeCommandAction.CommandParameterProperty); } set { base.SetValue(ExInvokeCommandAction.CommandParameterProperty, value); } } /// <summary> /// 調(diào)用操作。 /// </summary> /// <param name="parameter">操作的參數(shù)。如果操作不需要參數(shù),則可以將參數(shù)設(shè)置為空引用。</param> protected override void Invoke(object parameter) { if (base.AssociatedObject != null) { ICommand command = this.ResolveCommand(); /* * ★★★★★★★★★★★★★★★★★★★★★★★★ * 注意這里添加了事件觸發(fā)源和事件參數(shù) * ★★★★★★★★★★★★★★★★★★★★★★★★ */ ExCommandParameter exParameter = new ExCommandParameter { Sender=base.AssociatedObject, Parameter = GetValue(CommandParameterProperty), EventArgs=parameter as EventArgs }; if (command != null && command.CanExecute(exParameter)) { /* * ★★★★★★★★★★★★★★★★★★★★★★★★ * 注意將擴(kuò)展的參數(shù)傳遞到Execute方法中 * ★★★★★★★★★★★★★★★★★★★★★★★★ */ command.Execute(exParameter); } } } private ICommand ResolveCommand() { ICommand result = null; if (this.Command != null) { result = this.Command; } else { if (base.AssociatedObject != null) { Type type = base.AssociatedObject.GetType(); PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); PropertyInfo[] array = properties; for (int i = 0; i < array.Length; i++) { PropertyInfo propertyInfo = array[i]; if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType) && string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal)) { result = (ICommand)propertyInfo.GetValue(base.AssociatedObject, null); } } } } return result; } } }
<Window x:Class="EventArgsInViewModel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:loc="clr-namespace:EventArgsInViewModel" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <loc:MainWindowViewModel /> </Window.DataContext> <Grid> <Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="50,52,0,0" Name="button1" VerticalAlignment="Top" Width="138"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <!--★★★擴(kuò)展的InvokeCommandAction★★★--> <loc:ExInvokeCommandAction Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=button1}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Grid> </Window> ViewModel代碼
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Input; using Microsoft.Practices.Prism.Commands; using System.Windows; namespace EventArgsInViewModel { public class MainWindowViewModel { public ICommand ClickCommand { get { return new DelegateCommand<ExCommandParameter>((p) => { RoutedEventArgs args = p.EventArgs as RoutedEventArgs; MessageBox.Show(args.ToString()); }, (p) => { return true; } ); } } } }
|
|