2013-04-05 123 views
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"/> 

但現在上面的按鈕根本沒有被激活。

回答

0

你基本上擁有它。只需創建新的類StaticCommands.cs。

所有你需要做的就是,現在結合對static命令,因爲這樣的:

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

現在,您可以訪問按鈕元素,這意味着你還可以訪問CommandTarget屬性,如果需要。

看看這個:WPF Commands, How to declare Application level commands?

+0

嗨@Erti謝謝。現在按鈕從未啓用。令我沮喪的是,CanExecuteEventHandler_IfCanUndoVM從未受到影響。我已經編輯了完整圖片的問題。 – James 2013-04-05 08:57:31

+0

嘗試Command =「{x:Static local:StaticCommand.UndoVmCommand}」,而不是綁定它。我更新了我的帖子。 – 2013-04-05 18:20:47