理解命令
传统的设计在需要地方添加事件处理程序,并使用各个事件处理程序调用恰当的应用程序方法。如下图,许多应用程序任务可通过各种不同的路由触发,所以经常编写多个事件处理程序来调用相同的应用程序方法。本身这并不是什么问题。但当需要处理用户界面状态时,问题就变复杂了。如果要禁用PrintDocumnt()任务。需要禁用两个菜单命令和一个工具栏按钮,使它们不能被单击并且禁用Ctrl+P快捷键。编写代码完成这些工作很麻烦。
WPF使用新的命令模型解决这个问题。它增加了两个重要特性。
将事件委托到适当的命令。使控件的启用状态和相应命令的状态保持同步。
WPF命令模型
WPF命令模型具有如下4个重要元素
命令:命令表示应用程序任务,并且跟踪任务是否能被执行。然而,命令实际上不包含执行应用程序任务的代码。命令绑定:每个命令绑定针对用户界面的具体区域,将命令连接到相关的应用程序逻辑,这种分解的设计是非常重要的,因为每个命令可用于应用程序的多个地方, 并且每个地方具有不同的意义。为处理这一问题,需要同一命令与不同的命令绑定。命令源:命令源触发命令.例如:MenuItem和Button都是命令源。单击他们会执行绑定命令。命令目标:命令目标是在其中执行命令的元素。例如,Paste命令可在TextBox控件中插入文本,而OpenFile命令可在DocumentViewer中打开文档。
ICommand接口
WPF命令模型的核心是System.Windows.Input.ICommand接口。
public interface ICommand
{
void Execute(
object parameter);
bool CanExecute(
object parameter);
event EventHandler CanExecuteChanged;
}
Execute()方法将包含应用程序任务逻辑。
CanExecute()方法返回命令的状态。
通过CanExecuteChanged事件,当命令可用时,命令源可自动启用自身,当命令不可用时,禁用自身。
RoutedCommand类
RoutedCommand类是WPF中唯一实现了ICommand接口的类。所有WPF命令都是RoutedCommand类及其派生类的实例。
RoutedUICommand类
RoutedUICommand类继承自RoutedCommand类,WPF提供的所有预先构建好的命令都是RoutedUICommand对象。
命令库
WPF提供了基本命令库,基本命令库中保存的命令超过100条,这些命令通过以下5个专门的静态类的静态属性控制。
ApplicationCommands:该类提供了通用命令。包括剪切板命令(如Copy、Cut、Paste)以及文档命令(如New、Open、Save、Save As和Print)
NavigationCommands:该类提供了用于导航的命令,包括基于页面的应用程序设计的一些命令,如BrowseBack、BrowseForward和NextPage。
EditingCommands:该类提供了许多重要的文档编辑命令。包含用于移动的命令,MoveToLineEnd、MoveLeftByWord和MoveUpByPage,选择内容命令SelectToLineEnd、SelectLeftByWord。
ComponentCommands:改类提供了由用户界面组件使用的命令,包括用于移动和选择内容的命令,这些命令和EditingCommand类中的一些命令类似。
MediaCommands:该类提供了一组用于处理多媒体的命令,如Play、Pause、NextTrack以及IncreaseVolume。
命令源
命令库中的命令始终可用。触发他们最简单的方法是将他们关联到实现了ICommandSource接口的控件,其中包括继承自ButtonBase类的控件,Button和CheckBox、ListBoxItem、HypeLink以及MenuItem。
ICommandSource接口定义了三个属性
Command 指向连接的指令。
CommandParameter 提供其他希望随命令发送的数据。
CommandTarget确定将在其中执行命令的元素。
使用Command属性连接到ApplicationCommands.New
<Button Command="ApplicationCommands.New">New</Button>
命令绑定
当命令关联到命令源时,命令源将会被自动禁用。如上按钮,查询了命令的状态,而且由于命令还没有与其关联的绑定,所以按钮是禁用的。
代码创建绑定
CommandBinding binding =
new CommandBinding(ApplicationCommands.New);
binding.Executed+=
binding_Executed;
this.CommandBindings.Add(binding);
xaml
<Window.CommandBindings>
<CommandBinding Command=
"ApplicationCommands.New" Executed=
"binding_Executed"></CommandBinding>
</Window.CommandBindings>
<StackPanel>
<Button Command=
"ApplicationCommands.New">New</Button>
</StackPanel>
使用多命令源
<Menu>
<MenuItem Header=
"File">
<MenuItem Command=
"New"></MenuItem>
</MenuItem>
</Menu>
微调命令文本
菜单可以自动提取命令项文本。button 要实现此功能。
<Button Command=
"New" Content=
"{Binding RelativeSource={RelativeSource Self},Path=Command.Text}"></Button>
直接调用命令
ApplicationCommands.New.Execute(
null, targetElement);
this.CommandBindings[
0].Command.Execute(
null);
禁用命令
需求文本变时,保存按钮才可用
public GridDemoWindow()
{
InitializeComponent();
CommandBinding binding =
new CommandBinding(ApplicationCommands.Save);
binding.Executed+=
binding_Executed;
binding.CanExecute+=
binding_CanExecute;
this.CommandBindings.Add(binding);
}
private void binding_CanExecute(
object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute =
isDirty;
}
private void binding_Executed(
object sender, ExecutedRoutedEventArgs e)
{
throw new NotImplementedException();
}
private void txt_TextChanged(
object sender,RoutedEventArgs e)
{
isDirty =
true;
}
自定义命令
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; }
}
}
引用命名空间
xmlns:local=
"clr-namespace:Commands"
使用命令
<Window.CommandBindings>
<CommandBinding Command=
"local:DataCommands.Requery" Executed=
"binding_Executed"></CommandBinding>
</Window.CommandBindings>
<StackPanel>
<Button Command=
"local:DataCommands.Requery">Requery</Button>
</StackPanel>
转载于:https://www.cnblogs.com/lovezhangyu/p/10213918.html
相关资源:WPF命令(ICommand)基础学习代码