1

我有一种情况,我想为框架元素编写自定义命令。我做了如下:

public class UndoRedoManager
    {
        private static FrameworkElement frameworkElement;

        /// <summary>
        /// UndoVMCommand Attached properrty.
        /// </summary>
        public static readonly DependencyProperty UndoVMCommandProperty =
            DependencyProperty.RegisterAttached("UndoVMCommand", typeof(ICommand), typeof(UndoRedoManager), new FrameworkPropertyMetadata(UndoVmCommand, UndoVMCommand_PropertyChanged));

        /// <summary>
        /// UndoVMCommandProperty getter.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        [AttachedPropertyBrowsableForChildren]
        public static ICommand GetUndoVMCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(UndoVMCommandProperty);
        }

        /// <summary>
        /// UndoVMCommandProperty setter.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="value"></param>
        public static void SetUndoVMCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(UndoVMCommandProperty, value);
        }

        protected static void UndoVMCommand_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var control = obj as FrameworkElement;
            if (control != null)
            {
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    frameworkElement = control;
                }
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    frameworkElement = null;
                }
            }
        }
}

这是我附加在xaml中的:

<ItemsControl x:Name="graphControl" local:UndoRedoManager.UndoVMCommand="{Binding UndoCommand}">
......
</ItemsControl>

但是,我想在单击按钮时触发此命令。

<Button Content="Undo" CommandTarget="{Binding ElementName=graphControl}" Command="TheCommand" Margin="5"/>

非常喜欢

<Button Command="Copy" CommandTarget="{Binding ElementName=MyTextBox1}">Copy</Button>

所以我写了以下内容:

public static RoutedUICommand undoVmCommand = new RoutedUICommand("TheCommand", "TheCommand", typeof(UndoRedoManager));
        public static RoutedUICommand UndoVmCommand
        {
            get { return undoVmCommand; }
        }
        static UndoRedoManager()
        {
            CommandManager.RegisterClassCommandBinding(typeof(UndoRedoManager), new CommandBinding(undoVmCommand, ExecutedEventHandler_UndoVM, CanExecuteEventHandler_IfCanUndoVM));
        }

        private static void CanExecuteEventHandler_IfCanUndoVM(Object sender, CanExecuteRoutedEventArgs e)
        {
            FrameworkElement frmEle = sender as FrameworkElement;
            e.CanExecute = false;
            if (null != frmEle && frmEle.DataContext is ViewModelBase)
            {
                e.CanExecute = true;
                    //(frmEle.DataContext as GraphViewModel).CanUndo;
            }
            e.Handled = true;
        }

        public static void ExecutedEventHandler_UndoVM(Object sender, ExecutedRoutedEventArgs e)
        {
            FrameworkElement frmEle = sender as FrameworkElement;

            if (null != frmEle && frmEle.DataContext is ViewModelBase)
            {
                (frmEle.DataContext as GraphViewModel).UndoCommand.Execute(null);
            }
        }

我不明白那是怎么接线的。我应该在哪里声明上述路由命令?绝对不能在 FrameworkElement 类中做到这一点。有没有办法附上它?对不起,如果我无法清楚地说明问题。简而言之:如果我要以附加的方式为文本框编写“复制”命令,我该怎么做?

编辑:@Erti 发表评论后:

现在我有两个类,UndoRedoManager

public class UndoRedoManager
    {
        private static FrameworkElement frameworkElement;

        /// <summary>
        /// UndoVMCommand Attached properrty.
        /// </summary>
        public static readonly DependencyProperty UndoVMCommandProperty =
            DependencyProperty.RegisterAttached("UndoVMCommand", typeof(ICommand), typeof(UndoRedoManager), new FrameworkPropertyMetadata(StaticCommand.UndoVmCommand, UndoVMCommand_PropertyChanged));

        /// <summary>
        /// UndoVMCommandProperty getter.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        [AttachedPropertyBrowsableForChildren]
        public static ICommand GetUndoVMCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(UndoVMCommandProperty);
        }

        /// <summary>
        /// UndoVMCommandProperty setter.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="value"></param>
        public static void SetUndoVMCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(UndoVMCommandProperty, value);
        }

        protected static void UndoVMCommand_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var control = obj as FrameworkElement;
            if (control != null)
            {
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    frameworkElement = control;
                }
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    frameworkElement = null;
                }
            }
        }
     }

请注意注册依赖属性时在 PropertyMetadata 中传递的默认值。在 xaml 中,我将其用作:

<ItemsControl x:Name="graphControl" local:UndoRedoManager.UndoVMCommand="{Binding UndoCommand}"/>

另一个是 StaticCommand 类:

public class StaticCommand
    {
        public static RoutedUICommand undoVmCommand = new RoutedUICommand("TheCommand", "TheCommand", typeof(UndoRedoManager));
        public static RoutedUICommand UndoVmCommand
        {
            get { return undoVmCommand; }
        }
        static StaticCommand()
        {
            CommandManager.RegisterClassCommandBinding(typeof(StaticCommand), new CommandBinding(undoVmCommand, ExecutedEventHandler_UndoVM, CanExecuteEventHandler_IfCanUndoVM));
        }

        private static void CanExecuteEventHandler_IfCanUndoVM(Object sender, CanExecuteRoutedEventArgs e)
        {
            //This is not getting hit.
            e.CanExecute = true;
            e.Handled = true;
        }

        public static void ExecutedEventHandler_UndoVM(Object sender, ExecutedRoutedEventArgs e)
        {
            //I will do something here
        }
    }

在 xaml 中,我将其用作:

 <Button Content="Undo" CommandTarget="{Binding ElementName=graphControl}" Command="{Binding Source={x:Static local:StaticCommand.UndoVmCommand}}" Margin="5"/>

但是现在上面的按钮根本没有被激活。

4

1 回答 1

1

你基本上拥有它。只需创建新类 StaticCommands.cs。

您所要做的就是,现在绑定静态命令,如下所示:

<Button Command="{x:Static local:StaticCommands.UndoVmCommand}"
  CommandTarget="{Binding WHatever you want}" />

现在,在您的 ExecutedEventHandler_UndoVM 中,您可以访问 Button 元素,这意味着如果需要,您还可以访问 CommandTarget 属性。

也看看这个:WPF 命令,如何声明应用程序级命令?

于 2013-04-05T08:12:53.040 回答