自定義InvokeMouseCommandAction類,用於WPF中的鼠標事件到prism:DelegateCommand的綁定

可以實現鼠標事件綁定到DelegateCommand的功能,對prism中的InvokeCommandAction進行改寫,得到InvokeMouseCommandAction類。

該類使用很簡單,就是 <local:InvokeMouseCommandAction Command="{Binding MouseDownCommand}"/>,在xaml中的詳細語句如下:

   <Canvas Width="300" Height="300" Background="AliceBlue">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDown">
                    <local:InvokeMouseCommandAction Command="{Binding MouseDownCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Canvas>

在ViewModel中定時DelegateCommand<object>類型對象,不要定義爲DelegateCommand<Point>類型,否則會報
 “T for DelegateCommand<T> is not an object nor Nullable”錯誤,即T不是object或nullable類型的錯誤。

        public MainWindowViewModel()
        {
            MouseDownCommand = new DelegateCommand<object>(mHandler);
        }

        public DelegateCommand<object> MouseDownCommand { get; private set; }
        private void mHandler(object o)
        {
            //if(o is Point p)
           // MessageBox.Show(p.ToString());
        }

如果要對多種鼠標事件進行命令綁定,則xaml中使用方法如下:

   <Canvas Width="300" Height="300" Background="AliceBlue">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDown"> 
                    <local:InvokeMouseCommandAction Command="{Binding MouseDownCommand}"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="MouseMove">
                    <local:InvokeMouseCommandAction Command="{Binding MouseMoveCommand}"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="MouseUp">
                    <local:InvokeMouseCommandAction Command="{Binding MouseUpCommand}"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="MouseLeave">
                    <local:InvokeMouseCommandAction Command="{Binding MouseLeaveCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Canvas>

  下面是完整的InvokeMouseCommandAction代碼。該代碼通過修改prism:InvokeCommandParameter類的Invoke方法而得到。

 

 public  class InvokeMouseCommandAction:TriggerAction<UIElement>
    {
        private ExecutableCommandBehavior _commandBehavior;

        /// <summary>
        /// Dependency property identifying if the associated element should automaticlaly be enabled or disabled based on the result of the Command's CanExecute
        /// </summary>
        public static readonly DependencyProperty AutoEnableProperty =
            DependencyProperty.Register("AutoEnable", typeof(bool), typeof(InvokeMouseCommandAction),
                new PropertyMetadata(true, (d, e) => ((InvokeMouseCommandAction)d).OnAllowDisableChanged((bool)e.NewValue)));

        /// <summary>
        /// Gets or sets whther or not the associated element will automatically be enabled or disabled based on the result of the commands CanExecute
        /// </summary>
        public bool AutoEnable
        {
            get { return (bool)GetValue(AutoEnableProperty); }
            set { SetValue(AutoEnableProperty, value); }
        }

        private void OnAllowDisableChanged(bool newValue)
        {
            var behavior = GetOrCreateBehavior();
            if (behavior != null)
                behavior.AutoEnable = newValue;
        }

        /// <summary>
        /// Dependency property identifying the command to execute when invoked.
        /// </summary>
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(InvokeMouseCommandAction),
                new PropertyMetadata(null, (d, e) => ((InvokeMouseCommandAction)d).OnCommandChanged((ICommand)e.NewValue)));

        /// <summary>
        /// Gets or sets the command to execute when invoked.
        /// </summary>
        public ICommand Command
        {
            get { return GetValue(CommandProperty) as ICommand; }
            set { SetValue(CommandProperty, value); }
        }

        private void OnCommandChanged(ICommand newValue)
        {
            var behavior = GetOrCreateBehavior();
            if (behavior != null)
                behavior.Command = newValue;
        }

        /// <summary>
        /// Dependency property identifying the command parameter to supply on command execution.
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(InvokeMouseCommandAction),
                new PropertyMetadata(null, (d, e) => ((InvokeMouseCommandAction)d).OnCommandParameterChanged(e.NewValue)));

        /// <summary>
        /// Gets or sets the command parameter to supply on command execution.
        /// </summary>
        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        private void OnCommandParameterChanged(object newValue)
        {
            var behavior = GetOrCreateBehavior();
            if (behavior != null)
                behavior.CommandParameter = newValue;
        }

        /// <summary>
        /// Dependency property identifying the TriggerParameterPath to be parsed to identify the child property of the trigger parameter to be used as the command parameter.
        /// </summary>
        public static readonly DependencyProperty TriggerParameterPathProperty =
            DependencyProperty.Register("TriggerParameterPath", typeof(string), typeof(InvokeMouseCommandAction),
                new PropertyMetadata(null, (d, e) => { }));

        /// <summary>
        /// Gets or sets the TriggerParameterPath value.
        /// </summary>
        public string TriggerParameterPath
        {
            get { return GetValue(TriggerParameterPathProperty) as string; }
            set { SetValue(TriggerParameterPathProperty, value); }
        }

        /// <summary>
        /// Public wrapper of the Invoke method.
        /// </summary>
        public void InvokeAction(object parameter)
        {
            Invoke(parameter);
        }

        /// <summary>
        /// Executes the command
        /// </summary>
        /// <param name="parameter">This parameter is passed to the command; the CommandParameter specified in the CommandParameterProperty is used for command invocation if not null.</param>
        protected override void Invoke(object parameter)
        {
            //判斷是否對TriggerParameterPath進行了賦值,如果賦值則拋出異常
            if (!string.IsNullOrEmpty(TriggerParameterPath))
            {
                throw new ArgumentOutOfRangeException("TriggerParameterPath should not be assigned any value");
            }
            //判斷傳入的parameter是否爲 MouseEventArgs類型,如果佈置,則拋出異常。如果是,則計算得到鼠標點座標(相對於出發時間的UI對象),然後點座標傳入命令中
            if(parameter is MouseEventArgs mArgs)
            {
                Point p = mArgs.GetPosition((IInputElement)mArgs.Source);

                var behavior = GetOrCreateBehavior();

                if (behavior != null)
                {
                    behavior.ExecuteCommand(p);
                }
            }
            else
            {
                throw new InvalidOperationException("The Trigger event is not mouse relevant");
            }
     
        }

        /// <summary>
        /// Sets the Command and CommandParameter properties to null.
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            Command = null;
            CommandParameter = null;

            _commandBehavior = null;
        }

        /// <summary>
        /// This method is called after the behavior is attached.
        /// It updates the command behavior's Command and CommandParameter properties if necessary.
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            // In case this action is attached to a target object after the Command and/or CommandParameter properties are set,
            // the command behavior would be created without a value for these properties.
            // To cover this scenario, the Command and CommandParameter properties of the behavior are updated here.
            var behavior = GetOrCreateBehavior();

            behavior.AutoEnable = AutoEnable;

            if (behavior.Command != Command)
                behavior.Command = Command;

            if (behavior.CommandParameter != CommandParameter)
                behavior.CommandParameter = CommandParameter;
        }

        private ExecutableCommandBehavior GetOrCreateBehavior()
        {
            // In case this method is called prior to this action being attached, 
            // the CommandBehavior would always keep a null target object (which isn't changeable afterwards).
            // Therefore, in that case the behavior shouldn't be created and this method should return null.
            if (_commandBehavior == null && AssociatedObject != null)
            {
                _commandBehavior = new ExecutableCommandBehavior(AssociatedObject);
            }

            return _commandBehavior;
        }

        /// <summary>
        /// A CommandBehavior that exposes a public ExecuteCommand method. It provides the functionality to invoke commands and update Enabled state of the target control.
        /// It is not possible to make the <see cref="InvokeCommandAction"/> inherit from <see cref="CommandBehaviorBase{T}"/>, since the <see cref="InvokeCommandAction"/>
        /// must already inherit from <see cref="TriggerAction{T}"/>, so we chose to follow the aggregation approach.
        /// </summary>
        private class ExecutableCommandBehavior : CommandBehaviorBase<UIElement>
        {
            /// <summary>
            /// Constructor specifying the target object.
            /// </summary>
            /// <param name="target">The target object the behavior is attached to.</param>
            public ExecutableCommandBehavior(UIElement target)
                : base(target)
            {
            }

            /// <summary>
            /// Executes the command, if it's set.
            /// </summary>
            public new void ExecuteCommand(object parameter)
            {
                base.ExecuteCommand(parameter);
            }
        }


    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章