高级命令
自定义命令
通过实例化一个新的RoutedUICommand对象
最佳设计方式是遵循WPF库中的范例,并通过静态属性提供自定义命令。下面实例定义了名为Requery的命令
public class DataCommands
{
private static RoutedUICommand requery;
static DataCommands()
{
InputGestureCollection inputs=new InputGestureCollection();
inputs.Add(new KeyGesture(Key.R,ModifierKeys.Control,"Ctrl+R"));
requery=new RoutedUICommand("Requery","Requery",typeof(DataCommands),inputs);
}
public static RoutedUICommand Requery
{
get{return requery;}
}
}
在不同位置使用相同的命令
在WPF命令模型中,一个重要概念是范围(scope)。尽管没个命令仅有一份副本,但使用命令的效果却会根据触发命令的位置而异。例如,如果有两个文本框,他们都支持Cut、Copy和Paste命令,操作只会在当前具有焦点的文本框中发生。
然而,对于自己实现的命令——New,Open以及Save命令——情况就不痛了。问题在于当为这些命令中的某个命令触发Executed事件时,不知道该事件是属于第一个文本框还是第二个文本框。
解决方法是创建命令绑定,并向两个文本框的CommandBindings集合中添加同一个绑定。使用代码可很容易地完成该工作。如果希望使用XAML,需要使用WPF资源
<Window.Resources>
<CommandBinding x:key="binding" Command="ApplicationCommands.Save" Executed="SaveCommand" CanExecute="CanExecuteSave"></CommandBinding>
</Window.Resources>
<!- 为在标记的另一个位置插入该对象,可使用StaticResource标记扩展并提供键名 ->
<TextBox.CommandBindings>
<StaticResource ResourceKey="binding"></StaticResource>
</TextBox.CommandBindings>
使用命令参数
<Button Command="NavigationCommands.Zoom" CommandParameter="{Binding ElementName=txtZoom,Path=Text}">Zoom To Value</Button>
但是该方法并不总是有效,比如,在具有两个文件的文本编辑器中,没个文本框重用同一个Save按钮,但没个文本框需要使用不同的文件名。对于此类情况,必须在其他地方存储信息,或者需要通过代码触发命令,例如:
ApplicationCommands.New.Execute(theFileName,(Button)sender);
跟踪和翻转命令
为了构建这个解决方案,需要使用几项新技术,第一个细节是用于跟踪命令历史的类
每个CommandHistoryItem对象跟踪一下几部分信息
– 命令名称
– 执行命令的元素
– 再目标元素被改变了的属性
– 可用于保存受影响元素以前的状态的对象