방법: ICommandSource 구현
이 예제에서는 ICommandSource를 구현하여 명령 원본을 만드는 방법을 보여 줍니다. 명령 원본은 명령을 호출하는 방법을 알고 있는 개체입니다. ICommandSource 인터페이스는 다음 세 멤버를 노출합니다.
- Command: 호출될 명령입니다.
- CommandParameter: 명령 원본에서 명령을 처리하는 메서드로 전달되는 사용자 정의 데이터 형식입니다.
- CommandTarget: 명령이 실행되는 개체입니다.
이 예제에서는 Slider 컨트롤에서 상속되고 ICommandSource 인터페이스를 구현하는 클래스가 만들어집니다.
예제
WPF는 ICommandSource를 구현하는 다양한 클래스(예: Button, MenuItem 및 Hyperlink)를 제공합니다. 명령 원본은 명령을 호출하는 방법을 정의합니다. 이러한 클래스는 클릭할 때 명령을 호출하며, Command 속성이 설정된 경우에만 명령 원본 이 됩니다.
이 예제에서는 슬라이더가 이동되거나 더 정확하게는 Value 속성이 변경되면 명령을 호출합니다.
다음은 클래스 정의입니다.
public class CommandSlider : Slider, ICommandSource
{
public CommandSlider() : base()
{
}
Public Class CommandSlider
Inherits Slider
Implements ICommandSource
Public Sub New()
MyBase.New()
End Sub
다음 단계는 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);
}
}
' 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
다음은 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 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 속성을 덮어쓸 수 없습니다.
// 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;
}
}
' 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
다음 단계는 CanExecuteChanged 처리기에 대한 논리를 만드는 것입니다.
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;
}
}
}
}
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
마지막 단계는 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);
}
}
}
' 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
참고 항목
.NET Desktop feedback