HOW TO:實作 ICommandSource
更新:2007 年 11 月
本範例示範如何透過實作 ICommandSource 建立命令來源。命令來源是知道如何叫用 (Invoke) 命令的物件。ICommandSource 介面會公開三個成員:Command、CommandParameter 和 CommandTarget。Command 是要叫用的命令。CommandParameter 是從命令來源傳遞至處理命令之方法的使用者定義資料型別。CommandTarget 則是在其上執行命令的物件。
這個範中建立的類別會子類別化 (Subclass) Slider 控制項並實作 ICommandSource。如需完整的原始程式碼,請參閱實作 ICommandSource 範例。
範例
WPF 提供多個實作 ICommandSource 的類別,例如 Button、MenuItem 和 ListBoxItem。命令來源定義其叫用命令的方式。按一下 Button 和 MenuItem 時,會叫用命令。按兩下 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 範例會建立使用這個命令來源的範例應用程式。