(七)命令

命令使用步骤:

  • 创建命令类,即获得实现ICommand接口的一个类,创建RoutedCommand(与业务无关)或者其(或ICommand)的派生类(与业务有关)。
  • 声明命令实例
  • 指定命令源,即指定由谁来发命令,同一个命令可以有多个命令源。当吧命令指派给命令源的时候,命令源的使用会受到命令的影响。当命令不可用的时候,命令源的空件处于不可用状态。
  • 指定命令目标。命令目标不是命令的属性,而是命令源的属性。指定命令目标是告诉命令源向哪个组件发命令。无论这个组件是否有交点,它都会收到这个命令。若没有指定命令目标,则wpf系统认为当前拥有焦点的对象就是命令目标。
  • 设置命令关联,wpf命令需要CommandBinding在执行前来帮助判断是否可以执行。在执行后做一些事。

下面进行介绍命令系统基本元素的关系图:

这里写图片描述

命令源是命令的拥有者,命令反过来影响命令源状态

命令源用于命令目标,并且,命令源会一直向命令目标发消息。

命令目标然后会发送出可路由的事件(PreviewCanExecyte与CanExecute)

命令关联捕捉到这些事件后把命令能否发送实时的报告给命令。

一旦某个UI组件被命令源“瞄上”,命令源就会不断地向命令目标“投石问路”,命令目标就不停地发送可路由的PreviewCanExecyte与CanExecute附加事件,事件会沿着UI树向上传递并被命令关联所捕捉。命令关联捕捉到这些事件后会把命令能否发送实时报告给命令。类似的命令被发送出来到达命令目标,命令目标就会发送PreviewExecuteed和Executed两个附件事件,这两个事件也会随着Ui元素树向上传递并被命令关联所捕获,命令关联去完成一些后续的任务。

命令示例一

Xaml界面

<StackPanel x:Name="stackPanel">
       <Button x:Name="Button1" Content="SendCommand" Margin="5"/>
       <TextBox x:Name="TextBoxA" Margin="5,0" Height="100"/>
</StackPanel>

按照流程实现一个命令

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            InitializeCommand();
        }
        //定义命令
        private RoutedCommand clearCmd = new RoutedCommand("Clear",typeof(MainWindow));
        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();
            cb.Command = this.clearCmd;
            cb.CanExecute+=new CanExecuteRoutedEventHandler(cb_CanExecute);
            cb.Executed += new ExecutedRoutedEventHandler(cb_Executed);

            //将命令关联设置在textbox控件上
            this.TextBoxA.CommandBindings.Add(cb);
            //this.stackPanel.CommandBindings(cb);这样也可以。
        }

       //当命令送达目标后执行
        private void cb_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.TextBoxA.Clear();
            e.Handled = true; //避免继续向上传
        }
        //检测命令是否可以执行时执行。
        private void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(this.TextBoxA.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }

            e.Handled = true;//避免向上传影响性能。
        }
    }
}

对于上面的代码进行解释
- 命令在这里没有进行任何操作,只负责“跑腿”。

  • 对Text清理操作是由CommandBinding完成。在上面的例子中CommandBind捕捉到Executed事件就会调用cb_Executed。当捕捉到CanExecute事件则会反馈给命令源,影响命令源的状态。
  • CanExecuted事件的触发频率高,为了性能处理完后e.Handled设置为true隔断传播。
    #### 结果:
    这里写图片描述

带命令参数的示例

命令库里有好多Wpf的预制命令,(New,Open,Save…)这些命令是类的静态属性因此他们的实例只能有一个。这时就会有一个问题:如果由两个按钮都使用同一个命令,他们完成的任务不同,此时该怎么去分?下面示例进行解决这个问题:

<Grid Margin="6">
        <Grid.RowDefinitions>
            <RowDefinition Height="24"/>
            <RowDefinition Height="4"/>
            <RowDefinition Height="24"/>
            <RowDefinition Height="4"/>
            <RowDefinition Height="24"/>
            <RowDefinition Height="4"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Text="Name:" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Row="0"></TextBlock>
        <TextBox x:Name="nameTextBox" Margin="60,0,0,0" Grid.Row="0"></TextBox>
        <Button Name ="button1"  Content="New Teacher"  Command="ApplicationCommands.New" CommandParameter="Teacher" Grid.Row="2"/>
        <Button Name="button2" Content="New Student" Command="ApplicationCommands.New" CommandParameter="Student" Grid.Row="4"/>
        <ListBox x:Name="listBoxNewItems" Grid.Row="6"></ListBox>
</Grid>
<Window.CommandBindings>
        <CommandBinding  Command="ApplicationCommands.New"  CanExecute="New_CanExecute" Executed="New_Execute"/>
</Window.CommandBindings>

对应的cs代码

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void New_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
           if (string.IsNullOrEmpty(this.nameTextBox.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }
        }
        private void New_Execute(object sender, ExecutedRoutedEventArgs e)
        {
            string name = this.nameTextBox.Text;
            if (e.Parameter.ToString() == "Teacher")
            {
                this.listBoxNewItems.Items.Add(string.Format($"New Teacher:{name}"));
            }
            if (e.Parameter.ToString() == "Student")
            {
                this.listBoxNewItems.Items.Add(string.Format($"New Student:{name}"));
            }
        }
    }
运行结果:

这里写图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值