如何:实现 ICommandSource

更新:2007 年 11 月

本示例演示如何通过实现 ICommandSource 来创建命令源。 命令源是一个知道如何调用命令的对象。 ICommandSource 接口公开三个成员: CommandCommandParameterCommandTargetCommand 是将调用的命令。CommandParameter 是用户定义的数据类型,它从命令源传递到处理命令的方法。CommandTarget 是命令所作用于的对象。

在本示例中,创建这样一个类:它是 Slider 控件的子类并实现 ICommandSource。 有关完整的源代码,请参见实现接口 ICommandSource 示例

示例

WPF 提供许多实现 ICommandSource 的类,如 ButtonMenuItemListBoxItem。 命令源定义如何调用命令。ButtonMenuItem 在被单击时调用一个命令。 ListBoxItem 在被双击时调用一个命令。这些类只有在设置了 Command 属性时才会成为命令源。

对于本示例,我们将在滑块移动时调用命令,更准确地说,是在 Value 属性更改时调用命令。

类定义如下。

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

    }

下一步是实现 ICommandSource 成员。 在本示例中,属性实现为 DependencyProperty 对象。 这使属性可以使用数据绑定。 有关 DependencyProperty 类的更多信息,请参见依赖项属性概述。 有关数据绑定的更多信息,请参见数据绑定概述

这里只显示 Command 属性。

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

下面是 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 属性,因为必须先移除与前一个命令关联的事件处理程序(如果有的话)。

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

最后一步是为 CanExecuteChanged 处理程序和 Execute 方法创建逻辑。

CanExecuteChanged 事件通知命令源,在当前命令目标上执行命令的能力可能已更改。 当命令源接收到此事件时,通常会对命令调用 CanExecute 方法。 如果命令无法在当前命令目标上执行,那么命令源通常会禁用自身。 如果命令可以在当前命令目标上执行,那么命令源通常会启用自身。

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

最后一步是 Execute 方法。 如果命令是 RoutedCommand,则会调用 RoutedCommand Execute 方法;否则会调用 ICommand Execute 方法。

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

实现接口 ICommandSource 示例创建一个使用此命令源的示例应用程序。

请参见

概念

命令概述

参考

ICommandSource

ICommand

RoutedCommand