Практическое руководство. Реализация ICommandSource
Обновлен: Ноябрь 2007
В этом примере демонстрируется создание источника команды путем реализации ICommandSource. Источник команды представляет собой объект, который знает, как вызвать команду. Интерфейс ICommandSource предоставляет три элемента: Command, CommandParameter и CommandTarget. Command — команда, которая будет вызвана. CommandParameter — определенный пользователем тип данных, передаваемый из источника команды методу, обрабатывающему команду. CommandTarget — объект, над которым выполняется команда.
В этом примере создается класс, который является базовым классом для элемента управления Slider и реализует ICommandSource. Полный исходный код примера см. в разделе Пример реализации интерфейса ICommandSource.
Пример
WPF предоставляет несколько классов, которые реализуют ICommandSource, такие как Button, MenuItem и ListBoxItem. Источник команды определяет порядок вызова команды. Button и MenuItem вызывают команду при выполнении на них щелчка. ListBoxItem вызывает команду при выполнении на нем двойного щелчка. Эти классы становятся источниками команды, только когда установлено их свойство Command.
В данном примере команда будет вызываться при перемещении ползунка, или, точнее, при изменении свойства Value.
Ниже приведено определение класса.
public class CommandSlider : Slider, ICommandSource
{
public CommandSlider() : base()
{
}
Следующим шагом является реализация элементов ICommandSource. В этом примере свойства реализуются как объекты DependencyProperty. Это позволяет свойствам использовать привязку к данным. Дополнительные сведения о классе DependencyProperty см. в разделе Общие сведения о свойствах зависимости. Дополнительные сведения о привязке данных см. в разделе Общие сведения о связывании данных.
Здесь показано только свойство Command.
// Make Command a dependency property so it can use databinding.
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Command",
typeof(ICommand),
typeof(CommandSlider),
new PropertyMetadata((ICommand)null,
new PropertyChangedCallback(CommandChanged)));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
Ниже показан код обратного вызова изменения DependencyProperty.
// Command dependency property change callback.
private static void CommandChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
CommandSlider cs = (CommandSlider)d;
cs.HookUpCommand((ICommand)e.OldValue,(ICommand)e.NewValue);
}
Следующим шагом является добавление и удаление команды, связанной с источником команды. Свойство Command не может быть просто перезаписано при добавлении новой команды, поскольку сначала необходимо удалить обработчики событий, связанные с предыдущей командой, если таковая была.
// Add a new command to the Command Property.
private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
{
// If oldCommand is not null, then we need to remove the handlers.
if (oldCommand != null)
{
RemoveCommand(oldCommand, newCommand);
}
AddCommand(oldCommand, newCommand);
}
// Remove an old command from the Command Property.
private void RemoveCommand(ICommand oldCommand, ICommand newCommand)
{
EventHandler handler = CanExecuteChanged;
oldCommand.CanExecuteChanged -= handler;
}
// Add the command.
private void AddCommand(ICommand oldCommand, ICommand newCommand)
{
EventHandler handler = new EventHandler(CanExecuteChanged);
canExecuteChangedHandler = handler;
if (newCommand != null)
{
newCommand.CanExecuteChanged += canExecuteChangedHandler;
}
}
Последним шагом является создание логики для обработчика CanExecuteChanged и метода Execute.
Событие CanExecuteChanged сообщает источнику команды о возможном изменении способности выполнения команды для текущей цели команды. При получении этого события источник команды обычно вызывает метод CanExecute для команды. Если выполнение команды для текущей цели команды невозможно, источник команды обычно отключает себя. Если выполнение команды для текущей цели команды возможно, источник команды обычно включает себя.
private void CanExecuteChanged(object sender, EventArgs e)
{
if (this.Command != null)
{
RoutedCommand command = this.Command as RoutedCommand;
// If a RoutedCommand.
if (command != null)
{
if (command.CanExecute(CommandParameter, CommandTarget))
{
this.IsEnabled = true;
}
else
{
this.IsEnabled = false;
}
}
// If a not RoutedCommand.
else
{
if (Command.CanExecute(CommandParameter))
{
this.IsEnabled = true;
}
else
{
this.IsEnabled = false;
}
}
}
}
Последним шагом является метод Execute. Если команда представляет собой RoutedCommand, вызывается метод Execute у RoutedCommand; в противном случае вызывается метод ICommand Execute.
// If Command is defined, moving the slider will invoke the command;
// Otherwise, the slider will behave normally.
protected override void OnValueChanged(double oldValue, double newValue)
{
base.OnValueChanged(oldValue, newValue);
if (this.Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
{
command.Execute(CommandParameter, CommandTarget);
}
else
{
((ICommand)Command).Execute(CommandParameter);
}
}
}
Пример реализации интерфейса ICommandSource создает образец приложения, использующий этот источник команды.
См. также
Основные понятия
Общие сведения о системе команд