다음을 통해 공유


방법: ICommandSource 구현

업데이트: 2007년 11월

이 예제에서는 ICommandSource를 구현하여 명령 소스를 만드는 방법을 보여 줍니다. 명령 소스는 명령 호출 방법을 아는 개체입니다. ICommandSource 인터페이스는 Command, CommandParameterCommandTarget의 세 멤버를 노출합니다. Command는 호출될 명령입니다. CommandParameter는 명령 소스에서 명령을 처리하는 메서드로 전달되는 사용자 정의 데이터 형식입니다. CommandTarget은 명령이 실행되는 개체입니다.

이 예제에서는 Slider 컨트롤을 서브클래싱하고 ICommandSource를 구현하는 클래스를 만듭니다. 전체 소스 코드를 보려면 ICommandSource 구현 샘플을 참조하십시오.

예제

WPF에서는 Button, MenuItemListBoxItem과 같은 ICommandSource를 구현하는 많은 클래스를 제공합니다. 명령 소스는 명령을 호출하는 방법을 정의합니다. 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