Freigeben über


Gewusst wie: Implementieren von "ICommandSource"

Aktualisiert: November 2007

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 legt drei Member offen: 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. Den vollständigen Quellcode finden Sie unter Beispiel für das Implementieren von "ICommandSource".

Beispiel

WPF stellt verschiedene Klassen bereit, die ICommandSource implementieren, z. B. Button, MenuItem und ListBoxItem. Eine Befehlsquelle definiert, wie sie einen Befehl aufruft. 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 : 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 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 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 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 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 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);
        }
    }
}

Unter Beispiel für das Implementieren von "ICommandSource" wird eine Beispielanwendung erstellt, die diese Befehlsquelle verwendet.

Siehe auch

Konzepte

Befehlsübersicht

Referenz

ICommandSource

ICommand

RoutedCommand