1. 程式人生 > >整理:WPF中應用附加事件製作可以繫結命令的其他事件

整理:WPF中應用附加事件製作可以繫結命令的其他事件

目的:應用附加事件的方式定義可以繫結的事件,如MouseLeftButton、MouseDouble等等

一、定義屬於Control的附加事件ControlAttachEvent類

/// <summary> 附加事件 </summary>
    public static class ControlAttachEvent
    {

        #region - 雙擊事件 -

        public static readonly DependencyProperty PreviewMouseDoubleClickProperty =
            DependencyProperty.RegisterAttached("PreviewMouseDoubleClick", typeof(ICommand), typeof(ControlAttachEvent), new FrameworkPropertyMetadata(OnCommandChanged));

        public static ICommand GetPreviewMouseDoubleClick(Control target)
        {
            return (ICommand)target.GetValue(PreviewMouseDoubleClickProperty);
        }

        public static void SetPreviewMouseDoubleClick(Control target, ICommand value)
        {
            target.SetValue(PreviewMouseDoubleClickProperty, value);
        }

        private static void Element_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            Control control = sender as Control;

            ICommand command = GetPreviewMouseDoubleClick(control);
            
            if (command.CanExecute(sender))
            {
                command.Execute(sender);
                e.Handled = true;
            }
        }

        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Control control = d as Control;

            control.PreviewMouseDoubleClick += new MouseButtonEventHandler(Element_PreviewMouseDoubleClick);
        }
        #endregion

        public static DependencyProperty PreviewMouseLeftButtonDownCommandProperty = DependencyProperty.RegisterAttached("PreviewMouseLeftButtonDown",typeof(ICommand),typeof(ControlAttachEvent),new FrameworkPropertyMetadata(null, new PropertyChangedCallback(PreviewMouseLeftButtonDownChanged)));

        public static void SetPreviewMouseLeftButtonDown(DependencyObject target, ICommand value)
        {
            target.SetValue(PreviewMouseLeftButtonDownCommandProperty, value);
        }

        public static ICommand GetPreviewMouseLeftButtonDown(DependencyObject target)
        {
            return (ICommand)target.GetValue(PreviewMouseLeftButtonDownCommandProperty);
        }

        private static void PreviewMouseLeftButtonDownChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = target as FrameworkElement;
            if (element != null)
            {
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    element.PreviewMouseLeftButtonDown += element_PreviewMouseLeftButtonDown;
                }
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    element.PreviewMouseLeftButtonDown -= element_PreviewMouseLeftButtonDown;
                }
            }
        }

        private static void element_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;
            ICommand command = (ICommand)element.GetValue(PreviewMouseLeftButtonDownCommandProperty);
            command.Execute(sender);
        }
    }

說明:當控制元件MyControl中應用該項附加事件,如註冊PreviewMouseDoubleClick事件,則會觸發更新方法OnCommandChanged,而在更新方法中則會註冊該控制元件MyControl的雙擊事件繫結的命令,由此實現雙擊該控制元件觸發繫結命令的功能;

二、呼叫方法

  <Button  base:ControlAttachEvent.PreviewMouseDoubleClick="{Binding RelayCommand}"/>

 如上程式碼當雙擊Button時會觸發ViewModel中繫結的RelayCommand命令

注:

優點在於可以把控制元件中不支援繫結的事件支援繫結,同時應用附加屬性複用性更強

缺點在於傳遞事件的引數只有sender,agrs需要特殊處理,同時支援的事件與Control有關,其他更上層的控制元件需要單獨定義