Comment : implémenter ICommandSource
Cet exemple indique comment créer une source de commande en implémentant ICommandSource. Une source de commande est un objet qui sait comment appeler une commande. L'interface ICommandSource expose trois membres : Command, CommandParameter et CommandTarget. Command est la commande qui sera invoquée. CommandParameter est un type de données défini par l'utilisateur qui est transmis de la source de commande à la méthode qui gère la commande. CommandTarget est l'objet sur lequel est exécutée la commande.
Dans cet exemple, une classe qui sous-classe le contrôle Slider et implémente ICommandSource est créée.
Exemple
WPF fournit plusieurs classes qui implémentent ICommandSource, comme Button, MenuItem et ListBoxItem. Une source de commande définit comment appeler une commande. Button et MenuItem invoquent une commande lorsque vous cliquez dessus. ListBoxItem appelle une commande lorsque l'utilisateur double-clique dessus. Ces classes ne deviennent une source de commande que lorsque leur propriété Command est définie.
Dans cet exemple, nous appellerons la commande lorsque le curseur sera déplacé, ou plus précisément lorsque la propriété Value sera modifiée.
Les éléments suivants composent la définition de classe.
Public Class CommandSlider
Inherits Slider
Implements ICommandSource
Public Sub New()
MyBase.New()
End Sub
public class CommandSlider : Slider, ICommandSource
{
public CommandSlider() : base()
{
}
L'étape suivante consiste à implémenter les membres ICommandSource. Dans cet exemple, les propriétés sont implémentées en tant qu'objets DependencyProperty. Cela permet aux propriétés d'utiliser la liaison de données. Pour plus d'informations sur la classe DependencyProperty, consultez Vue d'ensemble des propriétés de dépendance. Pour plus d'informations sur la liaison de données, consultez Vue d'ensemble de la liaison de données.
Seule la propriété Command est illustrée ici.
' Make Command a dependency property so it can use databinding.
Public Shared ReadOnly CommandProperty As DependencyProperty =
DependencyProperty.Register("Command", GetType(ICommand),
GetType(CommandSlider),
New PropertyMetadata(CType(Nothing, ICommand),
New PropertyChangedCallback(AddressOf CommandChanged)))
Public ReadOnly Property Command1() As ICommand Implements ICommandSource.Command
Get
Return CType(GetValue(CommandProperty), ICommand)
End Get
End Property
Public Property Command() As ICommand
Get
Return CType(GetValue(CommandProperty), ICommand)
End Get
Set(ByVal value As ICommand)
SetValue(CommandProperty, value)
End Set
End Property
// 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);
}
}
Les éléments suivants représentent le rappel de changement DependencyProperty.
' Command dependency property change callback.
Private Shared Sub CommandChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim cs As CommandSlider = CType(d, CommandSlider)
cs.HookUpCommand(CType(e.OldValue, ICommand), CType(e.NewValue, ICommand))
End Sub
// 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);
}
L'étape suivante consiste à ajouter et supprimer la commande associée à la source de commande. La propriété Command ne peut pas être remplacée simplement à l'ajout d'une nouvelle commande car les gestionnaires d'événements éventuellement associés à la commande précédente doivent être supprimés en premier.
' Add a new command to the Command Property.
Private Sub HookUpCommand(ByVal oldCommand As ICommand, ByVal newCommand As ICommand)
' If oldCommand is not null, then we need to remove the handlers.
If oldCommand IsNot Nothing Then
RemoveCommand(oldCommand, newCommand)
End If
AddCommand(oldCommand, newCommand)
End Sub
' Remove an old command from the Command Property.
Private Sub RemoveCommand(ByVal oldCommand As ICommand, ByVal newCommand As ICommand)
Dim handler As EventHandler = AddressOf CanExecuteChanged
RemoveHandler oldCommand.CanExecuteChanged, handler
End Sub
' Add the command.
Private Sub AddCommand(ByVal oldCommand As ICommand, ByVal newCommand As ICommand)
Dim handler As New EventHandler(AddressOf CanExecuteChanged)
canExecuteChangedHandler = handler
If newCommand IsNot Nothing Then
AddHandler newCommand.CanExecuteChanged, canExecuteChangedHandler
End If
End Sub
// 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;
}
}
La dernière étape consiste à créer la logique du gestionnaire CanExecuteChanged et la méthode Execute.
L'événement CanExecuteChanged informe la source de commande que la possibilité d'exécuter la commande sur la cible de commande actuelle a peut-être changé. Lorsqu'une source de commande reçoit cet événement, elle appelle généralement la méthode CanExecute sur la commande. Si la commande ne peut pas s'exécuter sur la cible de la commande actuelle, la source de commande se désactivera d'elle-même en règle générale. Si la commande peut s'exécuter sur la cible, la source de commande s'activera d'elle-même en règle générale.
Private Sub CanExecuteChanged(ByVal sender As Object, ByVal e As EventArgs)
If Me.Command IsNot Nothing Then
Dim command As RoutedCommand = TryCast(Me.Command, RoutedCommand)
' If a RoutedCommand.
If command IsNot Nothing Then
If command.CanExecute(CommandParameter, CommandTarget) Then
Me.IsEnabled = True
Else
Me.IsEnabled = False
End If
' If a not RoutedCommand.
Else
If Me.Command.CanExecute(CommandParameter) Then
Me.IsEnabled = True
Else
Me.IsEnabled = False
End If
End If
End If
End Sub
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;
}
}
}
}
La dernière étape consiste en la méthode Execute. Si la commande est un RoutedCommand, la méthode RoutedCommandExecute est appelée ; sinon, la méthode ICommandExecute est appelée.
' If Command is defined, moving the slider will invoke the command;
' Otherwise, the slider will behave normally.
Protected Overrides Sub OnValueChanged(ByVal oldValue As Double, ByVal newValue As Double)
MyBase.OnValueChanged(oldValue, newValue)
If Me.Command IsNot Nothing Then
Dim command As RoutedCommand = TryCast(Me.Command, RoutedCommand)
If command IsNot Nothing Then
command.Execute(CommandParameter, CommandTarget)
Else
CType(Me.Command, ICommand).Execute(CommandParameter)
End If
End If
End Sub
// 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);
}
}
}