Freigeben über


Gewusst wie: Implementieren von "ICommandSource"

Dieses Beispiel zeigt, wie Sie eine Befehlsquelle erstellen, indem Sie ICommandSource implementieren. Eine Befehlsquelle ist ein Objekt, das weiß, wie ein Befehl aufgerufen wird. Die ICommandSource-Schnittstelle verfügt über drei Methoden: Command, CommandParameter und CommandTarget. Command ist der Befehl, der aufgerufen wird. Der CommandParameter ist ein benutzerdefinierter Datentyp, der von der Befehlsquelle an die Methode übergeben wird, die den Befehl verarbeitet. CommandTarget ist das Objekt, für das der Befehl ausgeführt wird.

In diesem Beispiel wird eine Klasse erstellt, die das Slider-Steuerelement als Unterklasse festlegt und ICommandSource implementiert.

Beispiel

WPF stellt verschiedene Klassen bereit, die das ICommandSource-Element implementieren, z. B. Button, MenuItem und ListBoxItem. Eine Befehlsquelle definiert, wie ein Befehl aufgerufen wird. Button und MenuItem rufen einen Befehl auf, wenn darauf geklickt wird. Ein ListBoxItem ruft einen Befehl auf, wenn darauf doppelt geklickt wird. Diese Klassen werden nur zu einer Befehlsquelle, wenn ihre Command-Eigenschaft festgelegt wird.

In diesem Beispiel wird der Befehl aufgerufen, wenn der Schieberegler verschoben wird, also eigentlich, wenn sich die Value-Eigenschaft ändert.

Unten ist die Klassendefinition angegeben.

Public Class CommandSlider
    Inherits Slider
    Implements ICommandSource
    Public Sub New()
        MyBase.New()

    End Sub
public class CommandSlider : Slider, ICommandSource
{
    public CommandSlider() : base()
    {

    }

Der nächste Schritt besteht darin, die ICommandSource-Member zu implementieren. In diesem Beispiel werden die Eigenschaften als DependencyProperty-Objekte implementiert. Auf diese Weise können die Eigenschaften die Datenbindung verwenden. Weitere Informationen zur DependencyProperty-Klasse finden Sie unter Übersicht über Abhängigkeitseigenschaften. Weitere Informationen zur Datenbindung finden Sie unter Übersicht über Datenbindung.

Hier ist nur die Command-Eigenschaft dargestellt.

' 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);
    }
}

Im Folgenden ist der Rückruf der DependencyProperty-Änderung dargestellt.

' 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);
}

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 Ereignishandler, die dem vorherigen Befehl (falls vorhanden) zugeordnet sind, zuerst entfernt werden müssen.

' 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;
    }
}

Der letzte Schritt besteht darin, die Logik für den CanExecuteChanged-Handler und die Execute-Methode zu erstellen.

Das CanExecuteChanged-Ereignis benachrichtigt die Befehlsquelle, dass sich die Fähigkeit des Befehls, für das aktuelle Befehlsziel ausgeführt zu werden, ggf. geändert hat. Wenn eine Befehlsquelle dieses Ereignis empfängt, ruft es für den Befehl normalerweise die CanExecute-Methode auf. Wenn der Befehl für das aktuelle Befehlsziel nicht ausgeführt werden kann, deaktiviert sich die Befehlsquelle in der Regel selbst. Wenn der Befehl für das aktuelle Befehlsziel ausgeführt werden kann, aktiviert sich die Befehlsquelle in der Regel selbst.

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;
            }
        }
    }
}

Der letzte Schritt ist die Execute-Methode. Wenn es sich bei einem Befehl um einen RoutedCommand handelt, 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 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);
        }
    }
}

Siehe auch

Referenz

ICommandSource

ICommand

RoutedCommand

Konzepte

Befehlsübersicht