共用方式為


HOW TO:實作 ICommandSource

更新:2007 年 11 月

本範例示範如何透過實作 ICommandSource 建立命令來源。命令來源是知道如何叫用 (Invoke) 命令的物件。ICommandSource 介面會公開三個成員:CommandCommandParameterCommandTargetCommand 是要叫用的命令。CommandParameter 是從命令來源傳遞至處理命令之方法的使用者定義資料型別。CommandTarget 則是在其上執行命令的物件。

這個範中建立的類別會子類別化 (Subclass) Slider 控制項並實作 ICommandSource。如需完整的原始程式碼,請參閱實作 ICommandSource 範例

範例

WPF 提供多個實作 ICommandSource 的類別,例如 ButtonMenuItemListBoxItem。命令來源定義其叫用命令的方式。按一下 ButtonMenuItem 時,會叫用命令。按兩下 ListBoxItem 也會叫用命令。您必須設定這些類別的 Command 屬性,它們才會變成命令來源。

針對這個範例,我們將在移動滑桿時 (正確來說就是 Value 變更) 時叫用命令。

以下為類別定義。

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

    }

下一個步驟是實作 ICommandSource 成員。在這個範例中,屬性會實作成 DependencyProperty 物件。這可以讓屬性使用資料繫結 (Data Binding)。如需 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 變更回呼 (Callback)。

// 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 屬性不能在加入新命令時直接加以覆寫,因為您必須先移除與先前命令相關聯的事件處理常式 (Event Handler) (如果有的話)。

// 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,則會呼叫 RoutedCommandExecute 方法,否則便會呼叫 ICommandExecute 方法。

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