命令的传递原理类似于路由事件,沿着VisualTree向上进行传递,但是和路由事件不同的是,它是有命令目标的,只有到达某个目标命令才会被执行。
总体来说,命令分为以下几个步骤:
(1)声明并定义命令类对象
每一个命令类都继承自ICommand类,或者直接使用RoutedCommand类(派生自ICommand)
(2)把命令赋值给命令源
命令源是命令的发送者,是实现了ICommandSource接口的类对象,很多的界面元素都实现了该接口,包括Button、MenuItem等等。这些界面元素都含有一个叫做Command的属性,我们要做的就是将第一步定义的命令类对象赋值给该属性。
(3)为命令源指定目标
上述命令源,含有一个叫做CommandTarget的属性,我们用实现了IInutElement接口的类对象为其赋值,而向TextBox等很多界面元素都实现了IInutElement接口。
(4)创建命令关联
命令关联,是一个CommandBinding对象,我们这里主要用到它的三个属性,Command被我们上面声明的命令类对象赋值,CanExcute被一个CanExecuteRoutedEventHandler事件处理器获取,主要作用是探测命令是否可执行。Executed被一个ExecutedRoutedEventHandler事件处理器赋值,主要是执行命令的操作。
(5)把命令关联安置在外围控件上
命令关联本质上就是一个命令的监听器,当命令源确认命令目标后,命令源就会源源不断的投石问路,命令目标会发出CanExecute的附加事件,沿着UI树向上传递,我们设置的外围控件就就会捕获到该事件,然后把命令能不能发送实时的通知给命令。而当命令具备发送条件时,命令目标又会发送Execute附加事件,沿着UI树传递到该外围控件,外围控件就会做出相应的操作。
以下,代码实现了通过按钮清空编辑框里面数据的功能:
界面代码:
<Window x:Class="_9_2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="grid">
<Button Content="清?空?" Height="23" HorizontalAlignment="Left" Margin="143,29,0,0" Name="button1" VerticalAlignment="Top" Width="197" />
<TextBox Height="207" HorizontalAlignment="Left" Margin="70,70,0,0" Name="textBox1" VerticalAlignment="Top" Width="368" />
</Grid>
</Window>
后台代码:
/// <summary>
/// MainWindow.xaml 的Ì?交?互£¤逻?辑-
/// </summary>
public partial class MainWindow : Window
{
//声¦¨´明¡Â和¨ª定¡§义°?命¨¹令¢?
private RoutedCommand clearCmd = new RoutedCommand("Clear", typeof(MainWindow));
public MainWindow()
{
InitializeComponent();
//把ã?命¨¹令¢?给?命¨¹令¢?源¡ä
this.button1.Command = clearCmd;
//指?定¡§命¨¹令¢?的Ì?目?标À¨º
this.button1.CommandTarget = this.textBox1;
//创ä¡ä建¡§命¨¹令¢?关?联¢a
CommandBinding cb = new CommandBinding();
cb.Command = this.clearCmd;
cb.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExcute);
cb.Executed+=new ExecutedRoutedEventHandler(cb_Executed);
//将?CommandBinding关?联¢a到Ì?外ªa围¡ì控?件t上¦?
grid.CommandBindings.Add(cb);
}
//探¬?测a命¨¹令¢?是º?否¤?可¨¦以°?执¡ä行D时º¡À,ê?此ä?方¤?法¤¡§被À?调Ì¡Â用®?
private void cb_CanExcute(object sender, CanExecuteRoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.textBox1.Text))
{
e.CanExecute = false;
}
else
{
e.CanExecute = true;
}
e.Handled = true;
}
private void cb_Executed(object sender, ExecutedRoutedEventArgs e)
{
this.textBox1.Clear();
e.Handled = true;
}
}
实现效果:
清空前:
清空后: