XAML中的命令

开发工具与关键技术:命令

作者:邓崇富

撰写时间:2019 年6 月3 日

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

命令系统的基本元素:

WPF的命令系统由下面几个基本要素构成:

  1. 命令(Command):WPF的命令实际上就是实现了ICommand接口的类,平时使用最多的是RoutedCommand类。
  2. 命令源(Command Source):即命令的发送者,是实现了ICommandSource接口的类。很多界面元素都实现了这个接口,其中包括Button、MenuItem、ListBoxItem等。
  3. 命令目标(Command Target):即命令将发送给谁,或者是命令的将作用在谁的身上。命令目标必须是实现了IInputElement接口的类。
  4. 命令关联(Command Binding):负责把一些外围逻辑与命令关联起来,比如执行之前对命令是否可以执行进行判断、命令执行之后还有那些后续的工作等。

基本元素之间的关系:

这些元素的关系体现在使用命令的过程中,大概步骤如下几步:

  1. 创建命令类:即获得一个实现ICommand接口的类,如果命令与具体的业务逻辑无关系则使用WPF类库中的RoutedCommand类即可。如果想得到与业务逻辑相关的专有命令,则需要创建RoutedCommand(或者ICommand接口)的派生类。
  2. 声明命令实例:使用命令是需要创建命令类的实例。这里有个技巧,一般情况下程序中某种操作只需要一个命令实例与之对应即可。比如对应“保存”这个操作,你可以拿同一个实例去命令每个组件执行其保存功能,因此程序中的命令多使用单件模式(Singletone     Pattern)以减少代码的复杂度。
  3. 指定命令的源:即指定由谁来发送这个命令。同一个命令可以有多个源。比如保存命令,即可以由菜单中的保存项来发送,也可以由工具栏中的保存图标来发送。。需要注意的是,一旦把命令指派给命令源,那么命令源就会受影响,当命令不能被执行的时候作为命令源的控件将处在不可用状态。还需要注意,各种控件发送命令的方法不尽相同,比如Button和MenuItem是单击时发送命令,而ListBoxItme单击时表示被选中所以双击时才发送命令。
  4. 指定命令目标:命令目标并不是命令的属性而是命令源的属性,指定命令目标是告诉命令源向哪个组件送命令,无论这个组是否拥有焦点它都会接收到这个命令。。如果没有为命令源指定命令目标,则WPF系统认为当前拥有焦点的对象就是命令目标。
  5. 设置命令关联:WPF命令需要CommandBinding在执行前来帮助判断是不是可执行。命令目标就会不停地发送出可路由的PreviewCanExecute和CanExecute附加事件,事件会沿着UI元素树向上传递并被命令关联所捕到,命令关联捕到这些事件后会把命令能不能发送实时报告给命令。类似的。如果命令被发送出来并到达命令目标,命令目标就会发送PreviewCanExecute和Execute两个附加事件,这两个附加事件也会沿着UI元素树向上传递并被命令关联所捕到,命令关联会完成一些后续的任务。

下面的例子是定义一个命令,使用Button来发送这个命令,当命令送达TextBox时TextBox会被清空(如果TextBox中没有文字则命令不可被发送)。

程序的XAML界面代码如下:

<Window x:Class="WPF课件练习.Window1"

 <!--此处省略了引用的命名空间-->

        xmlns:local="clr-namespace:WPF课件练习"

        mc:Ignorable="d"

        Title="Window1" Height="214.6" Width="260">

    <StackPanel x:Name="stackPanel">

        <Button x:Name="button1" Content="Send Command" Margin="5,50,5,10"/>

        <TextBox x:Name="textBoxA" Margin="5,0" Height="100"/>

    </StackPanel>

</Window>

下面是XAML后台代码:

using System.Windows;

using System.Windows.Input;

 

namespace WPF课件练习

{

    /// <summary>

    /// Window1.xaml 的交互逻辑

    /// </summary>

    public partial class Window1 : Window

    {

        public Window1()

        {

            InitializeComponent();

            InitializeCommand();

        }

        //声明并定义命令

        private RoutedCommand clearCmd = new RoutedCommand("Clear", typeof(Window));

        private void InitializeCommand()

        {

            //把命令赋值给命令源(发送者)并指定快捷键

            this.button1.Command = this.clearCmd;

            this.clearCmd.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));

            //指定命令目标

            this.button1.CommandTarget = this.textBoxA;

            //创建关联命令

            CommandBinding cb = new CommandBinding();

            //只关注与clearCmd相关的事件

            cb.Command = this.clearCmd;

            cb.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute);

            cb.Executed += new ExecutedRoutedEventHandler(cb_Executed);

            //把命令关联安置在外围控件上

            this.stackPanel.CommandBindings.Add(cb);

        }

        //当探测命令是否可以执行时,此方法被调用

        void cb_CanExecute(object sender,CanExecuteRoutedEventArgs e)

        {

            if (string.IsNullOrEmpty(this.textBoxA.Text))

            {

                e.CanExecute = false;

            }

            else

            {

                e.CanExecute = true;

            }

            //避免继续向上传而降低程序性能

            e.Handled = true;

        }

        //当命令送达目标后,此方法被调用

        void cb_Executed(object sender,ExecutedRoutedEventArgs e)

        {

            this.textBoxA.Clear();

            //避免继续向上传而降低程序性能

            e.Handled = true;

        }

    }

}

   运行程序后,在TextBox中输入文字之后Button在命令可执行状态的影响下改变为可用,此时单击Button或者按Alt+C键,TexBox都会被清空,效果图如下:

              

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值