Delen via


Hoe te: ICommandSource implementeren

In dit voorbeeld ziet u hoe u een opdrachtbron maakt door ICommandSourcete implementeren. Een opdrachtbron is een object dat weet hoe een opdracht moet worden aangeroepen. De ICommandSource-interface bevat drie leden:

  • Command: de opdracht die wordt aangeroepen.
  • CommandParameter: een door de gebruiker gedefinieerd gegevenstype dat vanuit de opdrachtbron wordt doorgegeven aan de methode waarmee de opdracht wordt verwerkt.
  • CommandTarget: het object waarop de opdracht wordt uitgevoerd.

In dit voorbeeld wordt een klasse gemaakt die wordt overgenomen van het Slider besturingselement en de ICommandSource-interface implementeert.

Voorbeeld

WPF biedt een aantal klassen die ICommandSourceimplementeren, zoals Button, MenuItemen Hyperlink. Een opdrachtbron definieert hoe een opdracht wordt aangeroepen. Deze klassen roepen een opdracht aan wanneer erop wordt geklikt en ze worden alleen een opdrachtbron wanneer hun eigenschap Command is ingesteld.

In dit voorbeeld roept u de opdracht aan wanneer de schuifregelaar wordt verplaatst, of nauwkeuriger, wanneer de eigenschap Value wordt gewijzigd.

Hier volgt de klassedefinitie:

public class CommandSlider : Slider, ICommandSource
{
    public CommandSlider() : base()
    {
    }
Public Class CommandSlider
    Inherits Slider
    Implements ICommandSource
    Public Sub New()
        MyBase.New()

    End Sub

De volgende stap is de ICommandSource-leden te implementeren. In dit voorbeeld worden de eigenschappen geïmplementeerd als DependencyProperty objecten. Hierdoor kunnen de eigenschappen gegevensbinding gebruiken. Zie voor meer informatie over de DependencyProperty-klasse het Afhankelijkheidseigenschappenoverzicht. Zie het Overzicht van gegevensbindingvoor meer informatie over gegevensbinding.

Alleen de eigenschap Command wordt hier weergegeven.

// 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

Hier volgt de callback van 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 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

De volgende stap bestaat uit het toevoegen en verwijderen van de opdracht die is gekoppeld aan de opdrachtbron. De eigenschap Command kan niet eenvoudig worden overschreven wanneer er een nieuwe opdracht wordt toegevoegd, omdat de gebeurtenis-handlers die zijn gekoppeld aan de vorige opdracht, als er een was, eerst moeten worden verwijderd.

// 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

De volgende stap is het maken van logica voor de CanExecuteChanged handler.

De CanExecuteChanged gebeurtenis meldt de opdrachtbron dat de mogelijkheid van de opdracht om uit te voeren op het huidige opdrachtdoel mogelijk is veranderd. Wanneer een opdrachtbron deze gebeurtenis ontvangt, wordt meestal de CanExecute methode voor de opdracht aangeroepen. Als de opdracht niet kan worden uitgevoerd op het huidige opdrachtdoel, wordt de opdrachtbron meestal zelf uitgeschakeld. Als de opdracht kan worden uitgevoerd op het huidige opdrachtdoel, wordt de opdrachtbron meestal zelf ingeschakeld.

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

De laatste stap is de methode Execute. Als de opdracht een RoutedCommandis, wordt de RoutedCommandExecute methode aangeroepen; anders wordt de ICommandExecute methode aangeroepen.

// 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

Zie ook