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

16 篇文章 5 订阅
3 篇文章 1 订阅

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

先来看普通的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>

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace EventArgsInViewModel {
	/// <summary>
	/// 扩展CommandParameter,使CommandParameter可以带事件参数
	/// </summary>
	public class ExCommandParameter {
		/// <summary>
		/// 事件触发源
		/// </summary>
		public DependencyObject Sender { get; set; }
		/// <summary>
		/// 事件参数
		/// </summary>
		public EventArgs EventArgs { get; set; }
		/// <summary>
		/// 额外参数
		/// </summary>
		public object Parameter { get; set; }
	}
}


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

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>
	/// 扩展的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>
		/// 获得或设置此操作应调用的命令的名称。
		/// </summary>
		/// <value>此操作应调用的命令的名称。</value>
		/// <remarks>如果设置了此属性和 Command 属性,则此属性将被后者所取代。</remarks>
		public string CommandName {
			get {
				base.ReadPreamble();
				return this.commandName;
			}
			set {
				if (this.CommandName != value) {
					base.WritePreamble();
					this.commandName = value;
					base.WritePostscript();
				}
			}
		}
		/// <summary>
		/// 获取或设置此操作应调用的命令。这是依赖属性。
		/// </summary>
		/// <value>要执行的命令。</value>
		/// <remarks>如果设置了此属性和 CommandName 属性,则此属性将优先于后者。</remarks>
		public ICommand Command {
			get {
				return (ICommand)base.GetValue(ExInvokeCommandAction.CommandProperty);
			}
			set {
				base.SetValue(ExInvokeCommandAction.CommandProperty, value);
			}
		}
		/// <summary>
		/// 获得或设置命令参数。这是依赖属性。
		/// </summary>
		/// <value>命令参数。</value>
		/// <remarks>这是传递给 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks>
		public object CommandParameter {
			get {
				return base.GetValue(ExInvokeCommandAction.CommandParameterProperty);
			}
			set {
				base.SetValue(ExInvokeCommandAction.CommandParameterProperty, value);
			}
		}
		/// <summary>
		/// 调用操作。
		/// </summary>
		/// <param name="parameter">操作的参数。如果操作不需要参数,则可以将参数设置为空引用。</param>
		protected override void Invoke(object parameter) {
			if (base.AssociatedObject != null) {
				ICommand command = this.ResolveCommand();

				/*
				 * ★★★★★★★★★★★★★★★★★★★★★★★★
				 * 注意这里添加了事件触发源和事件参数
				 * ★★★★★★★★★★★★★★★★★★★★★★★★
				 */
				ExCommandParameter exParameter = new ExCommandParameter {
					Sender=base.AssociatedObject,
					Parameter = GetValue(CommandParameterProperty),
					EventArgs=parameter as EventArgs

				};
				
				if (command != null && command.CanExecute(exParameter)) {
					/*
					 * ★★★★★★★★★★★★★★★★★★★★★★★★
					 * 注意将扩展的参数传递到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;
		}

	}
}


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

<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">
					<!--★★★扩展的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;
				}
				);
			}
		}
	}
}



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

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

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
在使用Prism.Mvvm进行事件时,可以使用以下方法来接收参数: 1. 使用CommandParameter属性传递参数:在View使用CommandParameter属性传递参数,并在ViewModel使用CommandParameter属性接收参数。 例如,在View义一个名为"SayHelloButton"的按钮: ```xaml <Button x:Name="SayHelloButton" Content="Say Hello" Command="{Binding SayHelloCommand}" CommandParameter="Prism.Mvvm" /> ``` 在ViewModel使用CommandParameter属性接收参数: ```csharp public ICommand SayHelloCommand { get; set; } public MyViewModel() { SayHelloCommand = new DelegateCommand<string>(SayHello); } private void SayHello(string name) { MessageBox.Show($"Hello, {name}!"); } ``` 点击按钮时,将会弹出"Hello, Prism.Mvvm!"的消息框。 2. 使用EventArgs参数传递参数:在View使用EventToCommand属性事件,并在ViewModel使用EventArgs参数接收参数。 例如,在View义一个名为"MouseDownCanvas"的Canvas: ```xaml <Canvas x:Name="MouseDownCanvas" Background="White" Width="200" Height="200"> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDown"> <i:InvokeCommandAction Command="{Binding MouseDownCommand}" /> </i:EventTrigger> </i:Interaction.Triggers> </Canvas> ``` 在ViewModel使用EventArgs参数接收参数: ```csharp public ICommand MouseDownCommand { get; set; } public MyViewModel() { MouseDownCommand = new DelegateCommand<MouseButtonEventArgs>(MouseDown); } private void MouseDown(MouseButtonEventArgs e) { MessageBox.Show($"Mouse down at ({e.GetPosition(null).X}, {e.GetPosition(null).Y})"); } ``` 在Canvas按下鼠标时,将会弹出鼠标点击位置的消息框。 这两种方法都可以实现参数的传递与接收。使用CommandParameter属性传递参数更为简单,但只能传递一个参数;使用EventArgs参数传递参数可以传递多个参数,但需要对事件进行
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值