• WPF自定义命令


    在讲述自定义命令之前,先了解一下与命令有关的几个要素,就像我们常说的“记叙文六要素”一样,一个完整的命令应当包括:

    1、命令,这当然是核心部分了;

    2、命令源:命令是谁发出的;

    3、目标,命令作用在哪些元素上,如往文本框中粘贴内容,那么该TextBox就是命令目标;

     

    严格上说,命令是实现了ICommand接口的类,但是,在际使用中,我们不必这样做,一种有效的方法是在某个类中直接声明一个RouteCommand类的成员字段即可,一般使用Static关键字,这样可以使得命令只与类有关,而不必理会其属于哪个实例。

    下面,我们一起动手完成一个实例:

    1、新建一个WPF应用程序,如何新建?(略);

    2、布局好主窗体,我们重点是需要两个文本框和一个按钮,其它的自己喜欢;

    3、使用CommadBinding把命令添加到窗体类的CommandBindings集合中。

    4、在按钮上设置Command属性。

    1.  <Window x:Class="CommandSample.MainWindow"  
    2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    4.     xmlns:c="clr-namespace:CommandSample"  
    5.     Title="命令示例" Height="100" Width="300">  
    6.     <!-- 添加命令绑定 -->  
    7.     <Window.CommandBindings>  
    8.         <CommandBinding Command="{x:Static c:MainWindow.MyCommand}"  
    9.                         CanExecute="MyCmd_CanExecute"  
    10.                         Executed="MyCmd_Executed"/>  
    11.     </Window.CommandBindings>  
    12.       
    13.     <Grid>  
    14.         <Grid.RowDefinitions>  
    15.             <RowDefinition Height="auto"/>  
    16.             <RowDefinition Height="auto"/>  
    17.         </Grid.RowDefinitions>  
    18.         <StackPanel Orientation="Horizontal" Grid.Row="0" Height="25" Margin="0,3,0,0" >  
    19.             <TextBox x:Name="txt01" Margin="2,0,0,0" Text="文本框一" Width="120"/>  
    20.             <TextBox x:Name="txt02" Margin="8,0,0,0" Text="文本框二" Width="120"/>  
    21.         </StackPanel>  
    22.         <Button x:Name="btnTest" Grid.Row="1"  
    23.                 Margin="80,5,80,0" Height="25" Content="执行命令"  
    24.                 Command="{x:Static c:MainWindow.MyCommand}"/>  
    25.     </Grid>  
    26. </Window>  

    在上面的XAML中,我们要注意的是,要引入我们定义了路由命令的类所在的命名空间。
     
    接下来,我们要编写两个事件处理程序——CanExecute确定命令是否可用;Executed命令逻辑应写在这里。
     
    1. // 命令  
    2. public static RoutedCommand MyCommand = new RoutedCommand();  
    3.   
    4. public MainWindow()  
    5. {  
    6.     InitializeComponent();  
    7.   
    8. }  
    9.   
    10. private void MyCmd_CanExecute(object sender, CanExecuteRoutedEventArgs e)  
    11. {  
    12.     if (e.Source != null)  
    13.     {  
    14.         e.CanExecute = true;  
    15.     }  
    16.     else { e.CanExecute = false; }  
    17. }  
    18.   
    19. private void MyCmd_Executed(object sender, ExecutedRoutedEventArgs e)  
    20. {  
    21.     if (e.Source != null)  
    22.     {  
    23.         var target = e.Source as Control;  
    24.         if (target != null)  
    25.         {  
    26.             if (target.Foreground == Brushes.Blue)  
    27.             {  
    28.                 target.Foreground = Brushes.Black;  
    29.             }  
    30.             else  
    31.             {  
    32.                 target.Foreground = Brushes.Blue;  
    33.             }  
    34.         }  
    35.     }  
    36. }  

    这样我们会有一个疑问,事件的引发者是谁?命令目标又是谁?

    我们在Executed事件处理程序的开始处下一个断点,然后单步跟入。

     
     

    得到的结果如下:

    sender是主窗体。

     

    ExecutedRoutedEventArgs的Source属性就是命令目标。

     
     

    但是,当我们运行的时候,我们发现字体变成蓝色的并不是文本框,而是按钮,为什呢?

    我们仔细阅读一下MSDN文档及相关说明就知道了,因为我们没有设置Target,所以,默认的是当前获得焦点的元素将成为命令目标。

    下面我们改一个上面的XAML让Button的CommandTarget指向第二个文本框。

    1. <Button x:Name="btnTest" Grid.Row="1"  
    2.        Margin="80,5,80,0" Height="25" Content="执行命令"  
    3.        Command="{x:Static c:MainWindow.MyCommand}"  
    4.        CommandTarget="{Binding ElementName=txt02}"/>  

    现在运行一下,可以发现,点击按钮后,第二个文本框的前景色就变成蓝色了。

     
     

    CanExecute事件和Executed事件都是路由事件,当然,RouteCommand类也包含遂道事件,至于什么是路由事件,什么是遂道事件,不在本文讲述的范围之中。

    以路由事件为例,下面我们来做第二个示例。这个示例,窗体上有一个StackPanel,里面包含一个按钮,同时,把CommandBinding添加到该StackPanel上,而该StackPanel里面再嵌套一个DockPanel,同样,把同一个命令也添加到DockPanel上,DockPanel里面再包含一个Canvas,但是Canvas不添加CommandBinding,然后,在Executed事件处理程序中分别输出引发事件的类型,命令目标类型和目标的Name属性的值。

     

    [XAML]

    1.  <Window x:Class="Cmd_Smpl2.Window1"  
    2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    4.     xmlns:c="clr-namespace:Cmd_Smpl2"  
    5.     Title="Window1" Height="300" Width="300">  
    6.     <Grid>  
    7.         <StackPanel Orientation="Vertical">  
    8.             <StackPanel.CommandBindings>  
    9.                 <CommandBinding Command="{x:Static c:Window1.MyCmdRoute}"  
    10.                                 CanExecute="Cmd_CanExecuteHandler"  
    11.                                 Executed="Cmd_ExecutedHandler"/>  
    12.             </StackPanel.CommandBindings>  
    13.             <Button x:Name="btnTest1" Width="100" Height="25"  
    14.                     Content="执行命令1"  
    15.                     Command="{x:Static c:Window1.MyCmdRoute}"/>  
    16.             <DockPanel>  
    17.                 <DockPanel.CommandBindings>  
    18.                     <CommandBinding Command="{x:Static c:Window1.MyCmdRoute}"  
    19.                                 CanExecute="Cmd_CanExecuteHandler"  
    20.                                 Executed="Cmd_ExecutedHandler"/>  
    21.                 </DockPanel.CommandBindings>  
    22.                 <Button x:Name="btnTest2" DockPanel.Dock="Top"  
    23.                         Content="执行命令2"  
    24.                         Command="{x:Static c:Window1.MyCmdRoute}"/>  
    25.                 <Canvas>  
    26.                     <Button x:Name="btnTest3"   
    27.                             Canvas.Top="3" Canvas.Left="5"  
    28.                             Width="100" Height="25"  
    29.                             Content="执行命令3"  
    30.                             Command="{x:Static c:Window1.MyCmdRoute}"/>  
    31.                 </Canvas>  
    32.             </DockPanel>  
    33.         </StackPanel>  
    34.     </Grid>  
    35. </Window>  

    [C# Code]

    1.  public static RoutedCommand MyCmdRoute = new RoutedCommand();  
    2. public Window1()  
    3. {  
    4.     InitializeComponent();  
    5. }  
    6.   
    7. private void Cmd_CanExecuteHandler(object sender, CanExecuteRoutedEventArgs e)  
    8. {  
    9.     e.CanExecute = e.Source == null ? false : true;  
    10. }  
    11.   
    12. private void Cmd_ExecutedHandler(object sender, ExecutedRoutedEventArgs e)  
    13. {  
    14.     if (e.Source != null && sender != null)  
    15.     {  
    16.         string msg = "引发事件的类型:{0},命令目标的类型:{1},命令目标的Name:{2}";  
    17.         System.Diagnostics.Debug.WriteLine(  
    18.                 string.Format(msg,  
    19.                               sender.GetType().Name,  
    20.                               e.Source.GetType().Name,  
    21.                               (e.Source as FrameworkElement).Name  
    22.             ));  
    23.     }  
    24. }  

    然后,我们运行程序,依次点击这三个按钮,接着打开“输出”窗口观察一下。

    得到的结果如下:

    1. 引发事件的类型:StackPanel,命令目标的类型:Button,命令目标的Name:btnTest1  
    2. 引发事件的类型:DockPanel,命令目标的类型:Button,命令目标的Name:btnTest2  
    3. 引发事件的类型:DockPanel,命令目标的类型:Button,命令目标的Name:btnTest3  

    发现了什么?从调试信息中看到,后两次执行命令,引发事件的类型都是DockPanel,这也符合路由事件沿可视化树往上冒泡的原则了。

    因为Canvas中我们没有绑定命令,所以在Canvas上无法引发事件,于是,向上路由到DockPanel,所以后两次事件的触发者都是DockPanel。

     

    接下来,我们还要动手做第三个示例,示例不通过控件来执行命令,而是通过快捷键Ctrl + Alt + Y来激活。

    1. public partial class Window1 : Window  
    2.   
    3.    public static RoutedCommand MyCmd = new RoutedCommand();  
    4.    public Window1()  
    5.    {  
    6.        InitializeComponent();  
    7.   
    8.        // 绑定事件  
    9.        CommandManager.AddCanExecuteHandler(thisthis.Cmd_CanExeHandler);  
    10.        CommandManager.AddExecutedHandler(thisthis.Cmd_ExeHandler);  
    11.        // 绑定命令  
    12.        this.InputBindings.Add(new KeyBinding(  
    13.            MyCmd,  
    14.            Key.Y,  
    15.            ModifierKeys.Control | ModifierKeys.Alt));  
    16.              
    17.    }  
    18.   
    19.    private void Cmd_CanExeHandler(object sender, CanExecuteRoutedEventArgs e)  
    20.    {  
    21.        e.CanExecute = true;  
    22.    }  
    23.   
    24.    private void Cmd_ExeHandler(object sender, ExecutedRoutedEventArgs e)  
    25.    {  
    26.        MessageBox.Show("命令已执行。");  
    27.    }  

    运行程序,当窗口处于活动状态,然后按下Ctrl + Alt + Y,你就看到效果了。

    文章来源:http://blog.csdn.net/tcjiaan/article/details/7213875

  • 相关阅读:
    HTML Strip Char Filter
    Creating a custom analyzer in ElasticSearch Nest client
    elasticsearch-analysis-pinyin
    ElasticSearch安装拼音插件 elasticsearch-analysis-pinyin
    Elasticsearch5.4 删除type
    Performs the analysis process on a text and return the tokens breakdown of the text
    Elasticsearch 5 Ik+pinyin分词配置详解
    线性可分支持向量机--SVM(1)
    感知机分类(perceptron classification)
    创建DateFrame的常用四种方式
  • 原文地址:https://www.cnblogs.com/luohengstudy/p/3117007.html
Copyright © 2020-2023  润新知