先看一下命令的简单使用:
<Window.CommandBindings> <CommandBinding Command="ApplicationCommands.Cut" CanExecute="CutCommand_CanExecute" Executed="CutCommand_Executed" /> <CommandBinding Command="ApplicationCommands.Paste" CanExecute="PasteCommand_CanExecute" Executed="PasteCommand_Executed" /> </Window.CommandBindings> <Window.InputBindings> <KeyBinding Gesture="Alt+X" Command="ApplicationCommands.Cut"></KeyBinding> <KeyBinding Modifiers="Alt" Key="V" Command="ApplicationCommands.Paste"></KeyBinding> </Window.InputBindings> <DockPanel> <WrapPanel DockPanel.Dock="Top" Margin="3"> <Button Command="ApplicationCommands.Cut" Width="60">_Cut</Button> <Button Command="ApplicationCommands.Paste" Width="60" Margin="3,0">_Paste</Button> </WrapPanel> <TextBox AcceptsReturn="True" Name="txtEditor" /> </DockPanel>
private void CutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = (txtEditor != null) && (txtEditor.SelectionLength > 0); } private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e) { txtEditor.Cut(); } private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = Clipboard.ContainsText(); } private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e) { txtEditor.Paste(); }
对比一下类似WinForm事件写法:
<DockPanel> <WrapPanel Margin="3" DockPanel.Dock="Top"> <Button Width="60" Click="Cut_Click">_Cut</Button> <Button Width="60" Margin="3,0" Click="Paste_Click">_Paste</Button> </WrapPanel> <TextBox Name="txtEditor" AcceptsReturn="True" /> </DockPanel>
private void Cut_Click(object sender, RoutedEventArgs e) { txtEditor.Cut(); } private void Paste_Click(object sender, RoutedEventArgs e) { txtEditor.Paste(); }
命令模式对比普通事件模式,可以通过CanExecute设置操作是否可用,可以比较方便的把操作绑定到点击按钮、快捷键等多种类型。
命令继承自ICommand接口,ICommand 公开了两种方法 Execute 和 CanExecute,以及一个事件 CanExecuteChanged。
命令的两个重要辅助属性,CommandTarget指定的命令的目标元素,CommandParameter设置命令参数,CommandManager在元素中添加和删除 PreviewExecuted、Executed、PreviewCanExecute 和 CanExecute 事件处理程序。
命令的优点不止以上的简单使用,最关键的是在使用MVVM模式中,命令和依赖属性配合通过Binding可以很好的做到UI和数据分离,降低View和Model的耦合。
命令直接绑定到元素控件上,一般会触发最常用属性,比如Button的Click,如果想绑定其他属性MoseMove的动作怎么办呢?
可以引入System.Windows.Interactivity.dll
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<Button Name="btn" Content="Button" Height="33" HorizontalAlignment="Left" Margin="40,24,0,0" VerticalAlignment="Top" Width="109"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="10" /> </i:EventTrigger> <i:EventTrigger EventName="MouseMove"> <i:InvokeCommandAction Command="{Binding Command2}" CommandParameter="{Binding ElementName=btn}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button>
使用System.Windows.Interactivity.dll不仅可以给Button、CheckBox等添加命令绑定,也可以给Image、Grid、Border等添加各种事件绑定。