绑定中继命令到Rectangle Vs MenuItem(未调用CanExecute())

时间:2015-04-06 19:15:26

标签: c# wpf

你好伙伴Overflowers:

我有一个在几个不同的上下文中使用的Relay命令类。 当我绑定到Rectangle(Shape)时,不调用CanExecute()方法。但是,当我将同一个类绑定到MenuItem时,会调用CanExecute()。当我开始查看菜单时似乎被调用。当CanExecute重新出现错误时,我的菜单项显示为灰色。很好!但是,我的应用程序有很多与CanExecute实现的形状。到目前为止,我必须从我的Excecute()方法为Shapes调用CanExecute。顺便说一句,我在构造时使用MouseBehaviors绑定了Shapes。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Sweeper.ViewModels
{
    public class
      RelayCommand : ICommand
    {
        #region Fields

        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _unexecute;
        private string _displayText;
        private string _category;

        private static EventHandler newLogItemEvent;
        public static event EventHandler NewLogItemEvent
        {
            add { newLogItemEvent += value; }
            remove { newLogItemEvent -= value; }
        }
        protected  virtual void OnNewLogItemEvent(LogItem li)
        {
            if (newLogItemEvent != null)
            {
                newLogItemEvent(null,li);
            }
        }
        private void RaiseNewLogItemEvent(LogItem li)
        {
            OnNewLogItemEvent(li);
        }
        //
        public string Category
        {
            get { return _category; }
            set { _category = value; }
        }

        #endregion // Fields

        #region Constructors

        //<summary>
        //Creates a new command that can always execute.
        //</summary>
        //<param name="execute">The execution logic.</param>
        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {

        }

        //<summary>
        //Creates a new command.
        //</summary>
        //<param name="execute">The execution logic.</param>
        //<param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
            : this(execute, canExecute, "")
        {
        }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute, string displayText)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
            _displayText = displayText;
        }


        public string DisplayText
        {
            get { return _displayText; }
            set { _displayText = value;
                  }
        }

        #endregion // Constructors

        #region ICommand Members

       // [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            if (_canExecute == null)
                return true;
            else
                return _canExecute(parameter);

        }

        public event EventHandler CanExecuteChanged
        {
            add    { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            bool sendLogItem = false;
            if (_canExecute != null)
            {
                if (_canExecute(parameter))
                {
                    _execute(parameter);
                    sendLogItem = true;

                }
            }
            else
            {
                _execute(parameter);
                sendLogItem = true;
            }

            if (sendLogItem)
            {
                string str;
                str = "Cmd:(" + _displayText + ")\tParm:(" + parameter + ")";
                RaiseNewLogItemEvent(new LogItem(this, str, parameter, _category));
            }
            else
            {  //Rejected 
            }
        }
        #endregion // ICommand Members  

    }

我要在下一个代码块中发布用于附加矩形对象的beaviors

    namespace Sweeper.Views
{
    public class MouseBehavior
    {
        #region MouseUp

        public static readonly DependencyProperty MouseUpCommandProperty =
            DependencyProperty.RegisterAttached("MouseUpCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseUpCommandChanged)));

        private static void MouseUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseUp += element_MouseUp;
        }

        static void element_MouseUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseUpCommand(element);

            command.Execute(e);
        }

        public static void SetMouseUpCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseUpCommandProperty, value);
        }

        public static ICommand GetMouseUpCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseUpCommandProperty);
        }

        #endregion

        #region MouseDown


        public static readonly DependencyProperty MouseDownCommandProperty =
            DependencyProperty.RegisterAttached("MouseDownCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseDownCommandChanged)));

        private static void MouseDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseDown += element_MouseDown;
        }

        static void element_MouseDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseDownCommand(element);

            command.Execute(e);
        }

        public static void SetMouseDownCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseDownCommandProperty, value);
        }

        public static ICommand GetMouseDownCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseDownCommandProperty);
        }

        #endregion

        #region MouseEnter

        public static readonly DependencyProperty MouseEnterCommandProperty =
            DependencyProperty.RegisterAttached("MouseEnterCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseEnterCommandChanged)));

        private static void MouseEnterCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseEnter += new MouseEventHandler(element_MouseEnter);
        }

        static void element_MouseEnter(object sender, MouseEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseEnterCommand(element);

            command.Execute(e);
        }

        public static void SetMouseEnterCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseEnterCommandProperty, value);
        }

        public static ICommand GetMouseEnterCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseEnterCommandProperty);
        }
        #endregion

        #region MouseLeave

        public static readonly DependencyProperty MouseLeaveCommandProperty =
            DependencyProperty.RegisterAttached("MouseLeaveCommand", 
                                                   typeof(ICommand), 
                                                   typeof(MouseBehavior), 
                                                   new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeaveCommandChanged)));

        private static void MouseLeaveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseLeave += new MouseEventHandler(element_MouseLeave);
        }

        static void element_MouseLeave(object sender, MouseEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseLeaveCommand(element);

            command.Execute(e);
        }

        public static void SetMouseLeaveCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseLeaveCommandProperty, value);
        }

        public static ICommand GetMouseLeaveCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseLeaveCommandProperty);
        }
        #endregion

        #region MouseLeftButtonDown

        public static readonly DependencyProperty MouseLeftButtonDownCommandProperty =
            DependencyProperty.RegisterAttached("MouseLeftButtonDownCommand", 
                                                typeof(ICommand), 
                                                typeof(MouseBehavior), 
                                                new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeftButtonDownCommandChanged)));

        private static void MouseLeftButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseLeftButtonDown += element_MouseLeftButtonDown;
        }

        static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseLeftButtonDownCommand(element);

            command.Execute(e);
        }

        public static void SetMouseLeftButtonDownCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseLeftButtonDownCommandProperty, value);
        }

        public static ICommand GetMouseLeftButtonDownCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseLeftButtonDownCommandProperty);
        }

        #endregion

        #region MouseLeftButtonUp

        public static readonly DependencyProperty MouseLeftButtonUpCommandProperty =
            DependencyProperty.RegisterAttached("MouseLeftButtonUpCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeftButtonUpCommandChanged)));

        private static void MouseLeftButtonUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseLeftButtonUp += element_MouseLeftButtonUp;
        }

        static void element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseLeftButtonUpCommand(element);

            command.Execute(e);
        }

        public static void SetMouseLeftButtonUpCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseLeftButtonUpCommandProperty, value);
        }

        public static ICommand GetMouseLeftButtonUpCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseLeftButtonUpCommandProperty);
        }

        #endregion

        #region MouseMove

        public static readonly DependencyProperty MouseMoveCommandProperty =
            DependencyProperty.RegisterAttached("MouseMoveCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseMoveCommandChanged)));

        private static void MouseMoveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseMove += new MouseEventHandler(element_MouseMove);
        }

        static void element_MouseMove(object sender, MouseEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseMoveCommand(element);

            command.Execute(e);
        }

        public static void SetMouseMoveCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseMoveCommandProperty, value);
        }

        public static ICommand GetMouseMoveCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseMoveCommandProperty);
        }

        #endregion

        #region MouseRightButtonDown

        public static readonly DependencyProperty MouseRightButtonDownCommandProperty =
            DependencyProperty.RegisterAttached("MouseRightButtonDownCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseRightButtonDownCommandChanged)));

        private static void MouseRightButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseRightButtonDown += element_MouseRightButtonDown;
        }

        static void element_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseRightButtonDownCommand(element);

            command.Execute(e);
        }

        public static void SetMouseRightButtonDownCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseRightButtonDownCommandProperty, value);
        }

        public static ICommand GetMouseRightButtonDownCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseRightButtonDownCommandProperty);
        }

        #endregion

        #region MouseRightButtonUp

        public static readonly DependencyProperty MouseRightButtonUpCommandProperty =
            DependencyProperty.RegisterAttached("MouseRightButtonUpCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseRightButtonUpCommandChanged)));

        private static void MouseRightButtonUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseRightButtonUp += element_MouseRightButtonUp;
        }

        static void element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseRightButtonUpCommand(element);

            command.Execute(e);
        }

        public static void SetMouseRightButtonUpCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseRightButtonUpCommandProperty, value);
        }

        public static ICommand GetMouseRightButtonUpCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseRightButtonUpCommandProperty);
        }

        #endregion

        #region MouseWheel

        public static readonly DependencyProperty MouseWheelCommandProperty =
            DependencyProperty.RegisterAttached("MouseWheelCommand", typeof(ICommand), typeof(MouseBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseWheelCommandChanged)));

        private static void MouseWheelCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)d;

            element.MouseWheel += new MouseWheelEventHandler(element_MouseWheel);
        }

        static void element_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;

            ICommand command = GetMouseWheelCommand(element);



            command.Execute(e);
        }

        public static void SetMouseWheelCommand(UIElement element, ICommand value)
        {
            element.SetValue(MouseWheelCommandProperty, value);
        }

        public static ICommand GetMouseWheelCommand(UIElement element)
        {
            return (ICommand)element.GetValue(MouseWheelCommandProperty);
        }

        #endregion

    }
}

确实绑定行为的数据模板

<DataTemplate x:Key="GamePieceTemplate">
            <Border  MinWidth="10" MinHeight="10" Padding="0" BorderBrush="{StaticResource GridBorderBrush}"  >
                <Rectangle   Style="{StaticResource GamePieceTrigger}"
                             StrokeThickness="1"  
                             vw:MouseBehavior.MouseLeftButtonDownCommand="{Binding MouseLeftButtonDownCommand}"
                             vw:MouseBehavior.MouseLeftButtonUpCommand="{Binding MouseLeftButtonUpCommand}"
                             vw:MouseBehavior.MouseEnterCommand="{Binding MouseEnterCommand}"
                             vw:MouseBehavior.MouseLeaveCommand="{Binding MouseLeaveCommand}"
                             vw:MouseBehavior.MouseRightButtonUpCommand="{Binding MouseRightButtonUpCommand}"           
                 />
            </Border>
        </DataTemplate>

然后这是一个违规(Not Calling CanExecute)命令

  #region MOUSE_LEFT_BUTTON_DOWN
    private RelayCommand _mouseLeftButtonDownCommand;
    public RelayCommand MouseLeftButtonDownCommand
    {
        get
        {
            if (_mouseLeftButtonDownCommand == null)
            {
                _mouseLeftButtonDownCommand = new RelayCommand(param => ExecuteMouseLeftButtonDown((MouseEventArgs)param),
                                                               param => CanExecuteMouseLeftButtonDown(null))
                {
                    DisplayText = "MouseLeftButtonDownCommand",
                    Category = CATEGORY
                };

            }
            return _mouseLeftButtonDownCommand;
        }
        set { _mouseLeftButtonDownCommand = value; }
    }
    private bool CanExecuteMouseLeftButtonDown(object o)
    {
        return ((!this.IsPlayed) && !(this.value == GameConstants.PieceValues.FLAGGED));

    }
    private void ExecuteMouseLeftButtonDown(MouseEventArgs e)
    {
        Debug.WriteLine("Mouse Down : " + e.GetPosition((IInputElement)e.Source));

        if (e.LeftButton == MouseButtonState.Pressed)
        {

            if (this.Value == GameConstants.PieceValues.BUTTON)
            {
                this.Value = GameConstants.PieceValues.PRESSED;
                gameBoard.GameState = GameConstants.GameStates.IN_DECISION;
            }
            else
                if (gameBoard.GameState != GameConstants.GameStates.WON &&
                    gameBoard.GameState != GameConstants.GameStates.LOST)
                    gameBoard.GameState = GameConstants.GameStates.IN_PLAY;


        }

    }
    #endregion

代码和命令被绑定我只是没有为MouseBehaviors自动调用CanExecute()。我确实在Execute方法中得到了我希望的调用。可能我只需要在我的Execute方法中调用CanExecute,就像我现在所做的那样?是对的吗?如果是这样的么?我想,为了使调用自动化,命令绑定的内容和方式可能很重要?

1 个答案:

答案 0 :(得分:0)

ICommand绑定到MenuItemButton时,WPF会自动调用其CanExecute()方法。这是因为how things are implemented in WPF

if (command.CanExecute(parameter))
{
    command.Execute(parameter);
}

由于Shape本身不支持命令,并且您通过附加属性添加此功能,因此您应该以相同的方式实现它。

所以,解决方案是:在您的事件处理程序中,替换

command.Execute(e);

if (command.CanExecute(e))
{
    command.Execute(e);
}