Condividi tramite


Procedura: implementare ICommandSource

In questo esempio viene mostrato come creare un'origine comando implementando ICommandSource. Un'origine comando è un oggetto in grado di richiamare un comando. L'interfaccia ICommandSource espone tre membri: Command, CommandParameter e CommandTarget. Command è il comando che verrà richiamato. CommandParameter è un tipo di dati definito dall'utente che viene passato dall'origine comando al metodo che gestisce il comando. CommandTarget è l'oggetto su cui si sta eseguendo il comando.

In questo esempio, viene generata una classe che crea una sottoclasse del controllo Slider e implementa ICommandSource.

Esempio

In WPF vengono fornite varie classi che implementano ICommandSource, ad esempio Button, MenuItem e ListBoxItem. Un'origine comando definisce il modo in cui richiama un comando. Le classi Button e MenuItem richiamano un comando quando vengono selezionate. La classe ListBoxItem richiama un comando quando viene selezionato con un doppio clic. Queste classi diventano un'origine comando solo quando viene impostata la proprietà Command.

In questo esempio, il comando viene richiamato quando il dispositivo di scorrimento viene spostato, o più precisamente, quando la proprietà Value viene modificata.

Di seguito viene riportata la definizione di classe.

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

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

    }

Il passaggio successivo consiste nell'implementazione dei membri ICommandSource. In questo esempio, le proprietà vengono implementate come oggetti DependencyProperty. Tale operazione consente alle proprietà di utilizzare l'associazione dati. Per ulteriori informazioni sulla classe DependencyProperty, vedere Cenni preliminari sulle proprietà di dipendenza. Per ulteriori informazioni sull'associazione dati, vedere Cenni preliminari sull'associazione dati.

Di seguito viene riportata solo la proprietà Command.

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

Di seguito viene riportato il callback di modifica 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);
}

Il passaggio successivo consiste nell'aggiunta e nella rimozione del comando associato all'origine comando. La proprietà Command non può semplicemente essere sovrascritta quando si aggiunge un nuovo comando, poiché è necessario innanzitutto rimuovere i gestori eventi associati al comando precedente, se presente.

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

L'ultimo passaggio consiste nella creazione della logica per il gestore CanExecuteChanged e il metodo Execute.

L'evento CanExecuteChanged notifica all'origine comando la probabile modifica della capacità del comando di essere eseguito nella destinazione comando corrente. Quando un'origine comando riceve questo evento, in genere chiama il metodo CanExecute del comando. Se non è possibile eseguire il comando nella destinazione comando corrente, l'origine comando in genere si disabilita. Se è possibile eseguire il comando nella destinazione comando corrente, l'origine comando in genere si attiva.

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

L'ultimo passaggio è rappresentato dal metodo Execute. Se il comando è RoutedCommand, viene chiamato il metodo Execute di RoutedCommand; in caso contrario, viene chiamato il metodo Execute di ICommand.

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

Vedere anche

Riferimenti

ICommandSource

ICommand

RoutedCommand

Concetti

Cenni preliminari sull'esecuzione di comandi