Compartir a través de


Cómo: Implementar ICommandSource

En este ejemplo se muestra cómo crear un origen de comando implementando ICommandSource. Un origen de comando es un objeto que sabe cómo invocar un comando. La interfaz ICommandSource expone tres miembros: Command, CommandParameter y CommandTarget. Command es el comando que se invocará. CommandParameter es un tipo de datos definido por el usuario que se pasa desde el origen de comando al método que administra el comando. CommandTarget es el objeto en que se ejecuta el comando.

En este ejemplo, se crea una clase que crea una subclase del control Slider e implementa ICommandSource.

Ejemplo

WPF proporciona varias clases que implementan ICommandSource, como Button, MenuItem y ListBoxItem. El origen de comando define cómo invoca un comando. Los objetos Button y MenuItem invocan un comando cuando se hace clic en ellos. Un objeto ListBoxItem invoca un comando cuando se hacer doble clic en él. Estas clases sólo se convierten en el origen de un comando cuando se establece su propiedad Command.

En este ejemplo se invoca al comando cuando se mueve el control deslizante, o dicho con más exactitud, cuando se cambia la propiedad Value.

A continuación, se muestra la definición de clase.

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

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

    }

El paso siguiente es implementar los miembros de ICommandSource. En este ejemplo, las propiedades se implementan como objetos DependencyProperty. Esto permite que las propiedades utilicen el enlace de datos. Para obtener más información sobre la clase DependencyProperty, vea Información general sobre las propiedades de dependencia. Para obtener más información sobre el enlace a datos, vea Información general sobre el enlace de datos.

Aquí se muestra únicamente la propiedad 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);
    }
}

Lo siguiente es la devolución de llamada de cambio de 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);
}

El paso siguiente consiste en agregar y quitar el comando que está asociado al origen de comando. No se puede sobrescribir simplemente la propiedad Command cuando se agrega un nuevo comando, porque antes se deben quitar los controladores de eventos asociados al comando anterior, si lo hay.

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

El último paso consiste en crear la lógica para el controlador de CanExecuteChanged y el método Execute.

El evento CanExecuteChanged notifica al origen de comando que es posible que haya cambiado la capacidad del comando para ejecutarse en el destino de comando actual. Cuando un origen de comando recibe este evento, normalmente llama al método CanExecute del comando. Si el comando no se puede ejecutar en el destino de comando actual, el origen de comando se suele deshabilitar. Si el comando sí se puede ejecutar en el destino de comando actual, el origen de comando se suele habilitar.

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

El último paso es el método Execute. Si el comando es RoutedCommand, se llama al método Execute de RoutedCommand; de lo contrario, se llama al método ICommand Execute.

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

Vea también

Referencia

ICommandSource

ICommand

RoutedCommand

Conceptos

Información general sobre comandos