方法 : ICommandSource を実装する

更新 : 2007 年 11 月

この例では、ICommandSource を実装してコマンド ソースを作成する方法を示します。コマンド ソースは、コマンドを呼び出す方法を認識しているオブジェクトです。ICommandSource インターフェイスは、CommandCommandParameter、および CommandTarget の 3 つのメンバを公開します。Command は、呼び出されるコマンドです。CommandParameter は、コマンド ソースからコマンドを処理するメソッドに渡されるユーザー定義のデータ型です。CommandTarget は、コマンドが実行されているオブジェクトです。

この例では、Slider コントロールをサブクラス化し、ICommandSource を実装するクラスが作成されます。ソース コード全体については、「ICommandSource の実装のサンプル」を参照してください。

使用例

WPF は、ButtonMenuItemListBoxItem などの ICommandSource を実装するさまざまなクラスを提供します。コマンド ソースは、コマンドを呼び出す方法を定義します。Button および MenuItem は、クリックされるとコマンドを呼び出します。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