WPF Prism框架下基于MVVM模式的命令、绑定、事件
Prism框架下的自定义路由事件和命令绑定 BaseCode
XAML代码:
<Button x:Class="IM.UI.CommandEx.PrismCommandEx" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> </Button>
CS代码:
public partial class PrismCommandEx : Button { public PrismCommandEx() { InitializeComponent(); } //定义一个路由事件 ClickTimeEx private readonly RoutedEvent ClickTimeExEvent = EventManager.RegisterRoutedEvent("ClickTimeEx", RoutingStrategy.Bubble, typeof(EventHandler<PrintTimeRoutedEventArgs>), typeof(PrismCommandEx)); public event RoutedEventHandler ClickTimeEx { add { AddHandler(ClickTimeExEvent, value); } remove { RemoveHandler(ClickTimeExEvent, value); } } private PrintTimeRoutedEventArgs routeEventArgs = null; //重写Button的OnClick事件,让Click事件去触发定义的ClickTimeEx事件 protected override void OnClick() { OnClickEx(); base.OnClick(); } //定义一个路由事件的处理函数 private void OnClickEx() { if (routeEventArgs == null) routeEventArgs = new PrintTimeRoutedEventArgs(ClickTimeExEvent, this, DateTime.Now); RaiseEvent(routeEventArgs); } }
public class PrintTimeRoutedEventArgs : RoutedEventArgs { public PrintTimeRoutedEventArgs(RoutedEvent routeEvent, object source) : base(routeEvent, source) { } public PrintTimeRoutedEventArgs(RoutedEvent routeEvent, object source, DateTime clickTime) : this(routeEvent, source) { this.ClickTime = clickTime; } public DateTime ClickTime { get; set; } }
public class InteractivesCommand : TriggerAction<DependencyObject> { private string commandName; //命令名称 //这里其实才是真正的执行命令的中转站,通过给定的命令去执行ViewModel protected override void Invoke(object parameter) { if (this.AssociatedObject != null) { ICommand command = this.ResolveCommand(); object[] tempObj = { parameter, CommandParameter, CommandParameterEx }; if ((command != null) && command.CanExecute(tempObj)) { command.Execute(tempObj); } } } public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } } public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractivesCommand), new UIPropertyMetadata(null)); public object CommandParameter { get { return (object)GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } } public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(InteractivesCommand), new UIPropertyMetadata(null, new PropertyChangedCallback((s, e) => { InteractivesCommand ic = s as InteractivesCommand; if (ic != null) ic.SynchronizeElementState(); }))); public object CommandParameterEx { get { return (object)GetValue(CommandParameterExProperty); } set { SetValue(CommandParameterExProperty, value); } } public static readonly DependencyProperty CommandParameterExProperty = DependencyProperty.Register("CommandParameterEx", typeof(object), typeof(InteractivesCommand), new UIPropertyMetadata(null, (s, e) => { InteractivesCommand ic = s as InteractivesCommand; if (ic != null) ic.SynchronizeElementState(); })); #region CRL属性 public string CommandName { get { this.ReadPreamble(); return this.commandName; } set { if (this.CommandName != value) { this.WritePreamble(); this.commandName = value; this.WritePostscript(); } } } #endregion private void SynchronizeElementState() { ICommand command = this.Command; if (command != null) { FrameworkElement associatedObject = this.AssociatedObject as FrameworkElement; if (associatedObject != null) { associatedObject.IsEnabled = command.CanExecute(CommandParameter); } } } private ICommand ResolveCommand() { ICommand command = null; if (this.Command != null) { return this.Command; } //在注册命令的时,Command为NULL,通过命令名称去在当前的依赖存储环境变量中去查找这个命令,并返回命令 //貌似记忆中有印象,就是说所有的依赖属性,在WPF中都有存放在某一个散列的集合中,在这个依赖属性被使用的时间,才会去创建一个实例,好像是依赖属性的特性 if (this.AssociatedObject != null) { foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal)) { command = (ICommand)info.GetValue(base.AssociatedObject, null); } } } return command; } }
public class PrismViewModel { public PrismViewModel() { } private DelegateCommand<Object> _commandWithEventArgs; public ICommand ClickTimeExCommand //要绑定的命令 { get { return _commandWithEventArgs ?? (_commandWithEventArgs = new DelegateCommand<object>(executeMethod, canExecuteMethod)); } } private void executeMethod(Object parameter) { //parameter 接收的值来源于 InteractivesCommand 类重写的Invoke方法,构建的object[]数据 MessageBox.Show("Prism框架MVVM设计模式测试"); } private bool canExecuteMethod(Object parameter) { return true; } }
控件调用:
<Window x:Class="IM.UI.WinPrismTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:myCommandEx="clr-namespace:IM.UI.CommandEx" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" Title="WinPrismTest" Height="300" Width="300"> <Window.DataContext> <myCommandEx:PrismViewModel/> </Window.DataContext> <Grid> <myCommandEx:PrismCommandEx x:Name="btnPrismMvvm" Content="Prism框架MVVM测试" VerticalAlignment="Top"> <i:Interaction.Triggers> <i:EventTrigger EventName="ClickTimeEx"> <myCommandEx:InteractivesCommand Command="{Binding ClickTimeExCommand}" CommandName="ClickTimeExCommand" CommandParameter="123" CommandParameterEx="567" /> </i:EventTrigger> </i:Interaction.Triggers> </myCommandEx:PrismCommandEx> </Grid> </Window>