ICommand 接口与 RoutedCommand
我们从一个简单的实列开始
1 <Window x:Class="WpfTutorialSamples.Commands.UsingCommandsSample" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="UsingCommandsSample" Height="100" Width="200"> 5 <Window.CommandBindings> 6 <CommandBinding Command="ApplicationCommands.New" Executed="NewCommand_Executed" CanExecute="NewCommand_CanExecute" /> 7 </Window.CommandBindings> 8 9 <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> 10 <Button Command="ApplicationCommands.New">New</Button> 11 </StackPanel> 12 </Window>
1 public partial class UsingCommandsSample : Window 2 { 3 public UsingCommandsSample() 4 { 5 InitializeComponent(); 6 } 7 8 private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) 9 { 10 e.CanExecute = true; 11 } 12 13 private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e) 14 { 15 MessageBox.Show("这是一个命令"); 16 } 17 } 18 }
通过将它添加到它的 CommandBindings 集合来在 Window 上定义一个命令绑定。我们指定我们希望使用的 Command(来自 ApplicationCommands 的 New 命令),以及两个事件处理程序。可视化界面由一个按钮组成,我们使用Command属性将命令附加到该按钮上 。
在代码隐藏中,我们处理两个事件。在CanExecute处理程序,WPF将调用当应用程序处于空闲状态,看看具体的命令是目前可用的,是这个例子很简单,因为我们希望这个特殊的命令可用的所有时间。这是通过将事件参数的CanExecute属性设置为 true 来完成的。
的执行的处理程序简单地示出了一个消息框被调用的命令时。如果你运行示例并按下按钮,你将看到此消息。需要注意的是,该命令定义了一个默认的键盘快捷键,这是一个额外的好处。您可以尝试按键盘上的 Ctrl+N,而不是单击按钮 - 结果是相同的。
Execute 与 CanExecute
Execute:命令执行(被执行的命令)
CanExecute:用于确认命令是否处于执行状态,所以当Execute被调用时,它将触发命令的执行.
使用 CanExecute 方法
在第一个实列中,实现了一个仅返回 true 的 CanExecute 事件,以便按钮始终可用。然而,这当然不适用于所有按钮 - 在许多情况下,希望根据应用程序中的某种状态启用或禁用按钮。
一个非常常见的例子是切换使用 Windows 剪贴板的按钮,希望剪切和复制按钮仅在选择文本时启用,粘贴按钮仅在剪贴板中存在文本时启用。
1 <Window x:Class="WpfTutorialSamples.Commands.CommandCanExecuteSample" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="CommandCanExecuteSample" Height="200" Width="250"> 5 <Window.CommandBindings> 6 <CommandBinding Command="ApplicationCommands.Cut" CanExecute="CutCommand_CanExecute" Executed="CutCommand_Executed" /> 7 <CommandBinding Command="ApplicationCommands.Paste" CanExecute="PasteCommand_CanExecute" Executed="PasteCommand_Executed" /> 8 </Window.CommandBindings> 9 <DockPanel> 10 <WrapPanel DockPanel.Dock="Top" Margin="3"> 11 <Button Command="ApplicationCommands.Cut" Width="60">_Cut</Button> 12 <Button Command="ApplicationCommands.Paste" Width="60" Margin="3,0">_Paste</Button> 13 </WrapPanel> 14 <TextBox AcceptsReturn="True" Name="txtEditor" /> 15 </DockPanel> 16 </Window>
1 public partial class CommandCanExecuteSample : Window 2 { 3 public CommandCanExecuteSample() 4 { 5 InitializeComponent(); 6 } 7 8 private void CutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) 9 { 10 e.CanExecute = (txtEditor != null) && (txtEditor.SelectionLength > 0); 11 } 12 13 private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e) 14 { 15 txtEditor.Cut(); 16 } 17 18 private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) 19 { 20 e.CanExecute = Clipboard.ContainsText(); 21 } 22 23 private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e) 24 { 25 txtEditor.Paste(); 26 } 27 } 28 }
所以,有一个非常简单的界面,有几个按钮和一个 TextBox 控件。第一个按钮将剪切到剪贴板,第二个按钮将从剪贴板粘贴。
在代码中,每个按钮都有两个事件:一个执行实际操作,名称以 _Executed 结尾,然后是 CanExecute 事件。在它们中的每一个,将看到我应用了一些逻辑来决定是否可以执行操作,然后将其分配给EventArgs 上的返回值 CanExecute。
你不必调用这些方法来更新你的按钮——当应用程序有空闲时间时,WPF 会自动执行它,确保你的界面始终保持更新。