WPF基础之命令

 理解命令

    传统的设计在需要地方添加事件处理程序,并使用各个事件处理程序调用恰当的应用程序方法。如下图,许多应用程序任务可通过各种不同的路由触发,所以经常编写多个事件处理程序来调用相同的应用程序方法。本身这并不是什么问题。但当需要处理用户界面状态时,问题就变复杂了。如果要禁用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>         
                                                                                                                                                                                        
posted @ 2019-01-03 14:15  SmilelyCoding  阅读(1432)  评论(3编辑  收藏  举报