Gewusst wie: Implementieren von "ICommandSource"
In diesem Beispiel wird gezeigt, wie Sie eine Befehlsquelle durch Implementieren der ICommandSource erstellen. Eine Befehlsquelle ist ein Objekt, das über die Fähigkeit zum Aufrufen eines Befehls verfügt. Die ICommandSource-Schnittstelle macht drei Member verfügbar:
- Command: Der Befehl, der aufgerufen wird.
- CommandParameter: Ein benutzerdefinierter Datentyp, der von der Befehlsquelle an die Methode übergeben wird, die den Befehl behandelt.
- CommandTarget: Das Objekt, auf das der Befehl angewendet wird.
In diesem Beispiel wird eine Klasse erstellt, die vom Slider-Steuerelement erbt und die ICommandSource-Schnittstelle implementiert.
Beispiel
WPF stellt eine Reihe von Klassen bereit, die ICommandSource implementieren, z. B. Button, MenuItem und Hyperlink. Eine Befehlsquelle definiert, wie ein Befehl aufgerufen wird. Diese Klassen rufen einen Befehl auf, wenn auf sie geklickt wird, und sie werden nur zu einer Befehlsquelle, wenn ihre Command-Eigenschaft festgelegt ist.
In diesem Beispiel rufen Sie den Befehl auf, wenn der Schieberegler verschoben wird oder genauer, wenn die Value-Eigenschaft geändert wird.
Nachfolgend sehen Sie die Klassendefinition:
public class CommandSlider : Slider, ICommandSource
{
public CommandSlider() : base()
{
}
Public Class CommandSlider
Inherits Slider
Implements ICommandSource
Public Sub New()
MyBase.New()
End Sub
Der nächste Schritt besteht im Implementieren der ICommandSource-Member. In diesem Beispiel werden die Eigenschaften als DependencyProperty-Objekte implementiert. Dadurch können die Eigenschaften Datenbindung verwenden. Weitere Informationen zur DependencyProperty-Klasse finden Sie in der Übersicht über die Abhängigkeitseigenschaften. Weitere Informationen zur Datenbindung finden Sie in der Übersicht über die Datenbindung.
Hier wird nur die Command-Eigenschaft gezeigt.
// 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);
}
}
' 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
Nachfolgend sehen Sie den DependencyProperty-Änderungsrückruf:
// 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 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
Der nächste Schritt besteht darin, den Befehl hinzuzufügen und zu entfernen, der der Befehlsquelle zugeordnet ist. Die Command-Eigenschaft kann nicht einfach überschrieben werden, wenn ein neuer Befehl hinzugefügt wird, da die dem vorherigen Befehl zugeordneten Ereignishandler, sofern vorhanden, zuerst entfernt werden müssen.
// 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;
}
}
' 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
Der nächste Schritt besteht darin, Logik für den CanExecuteChanged-Handler zu erstellen.
Das CanExecuteChanged-Ereignis teilt der Befehlsquelle mit, dass sich die Fähigkeit des Befehls zur Ausführung für das aktuelle Befehlsziel möglicherweise geändert hat. Wenn eine Befehlsquelle dieses Ereignis empfängt, ruft sie in der Regel die CanExecute-Methode für den Befehl auf. Wenn der Befehl nicht mit dem aktuellen Befehlsziel ausgeführt werden kann, deaktiviert sich die Befehlsquelle in der Regel selbst. Wenn der Befehl mit dem aktuellen Befehlsziel ausgeführt werden kann, aktiviert sich die Befehlsquelle in der Regel selbst.
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;
}
}
}
}
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
Der letzte Schritt ist die Execute-Methode. Wenn der Befehl ein RoutedCommand ist, wird die RoutedCommand Execute-Methode aufgerufen. Andernfalls wird die ICommand Execute-Methode aufgerufen.
// 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);
}
}
}
' 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
Weitere Informationen
.NET Desktop feedback