WPF Prism框架下基于MVVM模式的命令绑定事件

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF Prism框架下基于MVVM模式的命令绑定事件相关的知识,希望对你有一定的参考价值。

原文: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>
View Code

  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);
        }
    }
PrismCommandEx
技术图片
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; }
    }
PrintTimeRoutedEventArgs
技术图片
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;
        }

    }
InteractivesCommand
技术图片
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;
        }
    }
PrismViewModel

  控件调用:

技术图片
<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>
View Code

 

以上是关于WPF Prism框架下基于MVVM模式的命令绑定事件的主要内容,如果未能解决你的问题,请参考以下文章

wpf MVVM框架基础

.NET6+WPFWPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

C# WPF MVVM模式Prism框架从零搭建(经典)

.NET Core 3 WPF MVVM框架 Prism系列之导航系统

C# WPF MVVM模式Prism框架从零搭建(经典)

wpf mvvm模式 Icommand接口应该如何理解?