Пользовательская команда
У меня есть ситуация, когда я хочу написать пользовательскую команду для элемента рамки. Что я сделал, как показано ниже:
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. Есть ли способ прикрепить это? Прошу прощения, если я не смог четко сформулировать проблему. Короче говоря, простым способом: если бы я должен был написать команду "Копировать" для текстового поля в прикрепленном виде, как я могу это сделать?
РЕДАКТИРОВАТЬ: После комментария @ Эрти:
Теперь у меня есть два класса, 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"/>
Но теперь вышеуказанная кнопка вообще не активируется.
1 ответ
У вас в основном это есть. Просто создайте новый класс StaticCommands.cs.
Все, что вам нужно сделать, это теперь связать со статической командой, как таковой:
<Button Command="{x:Static local:StaticCommands.UndoVmCommand}"
CommandTarget="{Binding WHatever you want}" />
Теперь в вашем ExecutedEventHandler_UndoVM у вас есть доступ к элементу Button, что означает, что вы также можете получить доступ к свойству CommandTarget, если это необходимо.
Проверьте это тоже: WPF Commands, Как объявить команды уровня приложения?