【WPF】Command 自定义命令

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【WPF】Command 自定义命令相关的知识,希望对你有一定的参考价值。

参考技术A 在使用 MVVM 结构的 WPF 程序中,ViewModel 对 View 的响应是通过 Command (命令)来完成的。比如用户点了某个按键,使得与该按键相绑定的命令被触发,而该命令又是在 ViewModel 中被定义的,于是就完成了一次 View 对 ViewModel 的调用。

WPF 和 C# 语言的高级用法,比如委托、反射、事件等等,是紧密联系的,所以学习 WPF 时需要有一定的 C# 基础。

虽然官方提供了一些常用命令,但本文还是着重于自定义命令的用法。

命令有两大要素:做什么、能做吗。自定义命令首先要继承自 ICommand :

如上所示, ICommand 的后代有三个东西必须要实现,而最后两个 ExecuteAction 和 CanExecuteAction 是比较推荐的写法。

在本例中, Execute() 方法是 ICommand 认定的用来执行命令的方法, ExecuteAction 是对该方法的一项委托,于是外部使用者(ViewModel)只需设置这份委托,而不需染指 Execute() 方法。

接下来把这个命令类放在 ViewModel 中使用:

ViewModel 中定义了两个函数,分别对应命令的“做什么”、“能做吗”,并通过委托的方式告诉命令。

剩下的就是 View 中的内容了:

在 View 的 xaml 文件中,首先把 ViewModel 当作它的 DataContext (毕竟 ViewModel 其实就是 View 的 Model)。然后直接在按钮上用 Binding 的方式绑定命令。于是当用户点击按钮时,这个命令就会被触发。

命令被触发时,它会先调用自己的 CanExecute() 方法,这个方法在第一步中调用 CanExecuteAction 这个委托,这份委托又在第二步中绑定了 CanDoSomething() 方法……经过一番长途跋涉之后终于调用了 DoSomething() 方法 😶。

感受:如果按照老办法,按钮响应只需设一个 OnClick 的方法就成了,简单清爽,完全不必大费周章搞这么多事。可当程序到了一定规模,旧的思路就使维护变得难以维系。做界面还是应该养成良好的习惯

先创建一个命令:

然后为“做什么”和“能做吗”定义两个方法:

最后在 xaml 里面进行绑定:

WPF 自定义快捷键命令(COMMAND)(转)

命令简介

     WPF 中的命令是通过实现 ICommand 接口创建的。ICommand 公开两个方法(Execute 及 CanExecute)和一个事件(CanExecuteChanged)。Execute 执行与命令关联的操作。CanExecute 确定是否可以在当前命令目标上执行命令。如果集中管理命令操作的命令管理器检测到命令源中发生了更改,此更改可能使得已引发但尚未由命令绑定执行的命令无效,则将引发 CanExecuteChanged。ICommand 的 WPF 实现是 RoutedCommand 类。

     WPF 中的主要输入源是鼠标、键盘、墨迹和路由命令。更加面向设备的输入使用 RoutedEvent 来通知应用程序页中的对象已发生了输入事件。RoutedCommand 没有不同。RoutedCommand 的 Execute 和 CanExecute 方法不包含命令的应用程序逻辑,而是引发这样的路由事件:沿元素树以隧道和冒泡形式传递,直到遇到具有 CommandBinding 的对象。CommandBinding 包含这些事件的处理程序,执行此命令的就是这些处理程序。

     RoutedCommand 上的 Execute 方法在命令目标上引发 PreviewExecuted 和 Executed 事件。RoutedCommand 上的 CanExecute 方法在命令目标上引发 CanExecute 和 PreviewCanExecute 事件。这些事件沿元素树以隧道和冒泡形式传递,直到遇到具有该特定命令的 CommandBinding 的对象。

     WPF 提供了一组常用的路由命令,这组命令分布在几个类中:MediaCommandsApplicationCommandsNavigationCommandsComponentCommands 和 EditingCommands。这些类仅包含 RoutedCommand 对象,而不包含命令的实现逻辑。实现逻辑由其上执行命令的对象负责。[1]

自定义命令

     除了上述WPF 自带的RoutedCommand,还可以使用RoutedUICommand 类创建用户自定义命令,下面将通过一个实例详细讲解。首先新建一个WPF 项目,在其中加入一个TextBlock。目的是通过快捷键组合“Ctrl+Alt+I”和“Ctrl+Alt+D”改变字体大小,由“Ctrl+Alt+C”随机改变字体颜色。

<Grid>
    <TextBlock x:Name="textBlock1" Text="Hello World" HorizontalAlignment="Center"
               FontSize="10" Margin="42,29,46,41" Width="293" />
        
</Grid>

首先在Window.Resources 中定义两个RoutedUICommand,分别用于增加和减小字体尺寸。

<Window.Resources>
    <RoutedUICommand x:Key="IncreaseFontSize" Text="Increase Font Size" />
    <RoutedUICommand x:Key="DecreaseFontSize" Text="Decrease Font Size" />
</Window.Resources>

     通过KeyBinding 为上面两个命令绑定快捷键,按键组合可使用“+”进行连接。下面代码分别通过Modifiers+Key 和Gesture 两种方式为定义快捷键组合方式。大家可以任选其一进行使用,MSDN 中建议使用Gesture 方式定义以免发生混淆。

<Window.InputBindings>
    <KeyBinding Modifiers="Ctrl+Alt" Key="I" Command="{StaticResource IncreaseFontSize}"/>
    <KeyBinding Gesture="Ctrl+Alt+D" Command="{StaticResource DecreaseFontSize}"/>
</Window.InputBindings>

     接下来就要通过CanExecute和Excuted 为命令绑定相关的事件,CanExecute 负责判断能否执行命令(即Executed 定义的事件),Executed 就负责去执行用户定义的操作命令。

<Window.CommandBindings>
    <CommandBinding Command="{StaticResource IncreaseFontSize}"
                    CanExecute="CommandBinding_Increase_CanExecute"
                    Executed="CommandBinding_Increase_Executed"/>
    <CommandBinding Command="{StaticResource DecreaseFontSize}"
                    CanExecute="CommandBinding_Decrease_CanExecute"
                    Executed="CommandBinding_Decrease_Executed"/>
</Window.CommandBindings>

     至此,我们在XAML 中对命令的定义已经完成。下面进入到C# 中编写命令事件相关内容。扩大字体尺寸时通过CommandBinding_Increase_CanExecute 判断当前字体是否小于50,否则不会执行Executed 命令。若字体尺寸在50以内则通过CommandBinding_Increase_Executed 每次增加5。缩小尺寸时则不低于5。

private void CommandBinding_Increase_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    if (textBlock1.FontSize > 50)
    {
        e.CanExecute = false;
    }
    else
    {
        e.CanExecute = true;
    }
}

private void CommandBinding_Increase_Executed(object sender, ExecutedRoutedEventArgs e)
{
    textBlock1.FontSize += 5;
}

private void CommandBinding_Decrease_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    if (textBlock1.FontSize <= 5)
    {
        e.CanExecute = false;
    }
    else
    {
        e.CanExecute = true;
    }
}

private void CommandBinding_Decrease_Executed(object sender, ExecutedRoutedEventArgs e)
{
    textBlock1.FontSize -= 5;
}

运行程序使用“Ctrl+Alt+I”或 “Ctrl+Alt+D”改变字体大小。

  除了在XAML 中定义RoutedUICommand 我们也可以直接用C#定义,下面继续完成修改字体颜色的快捷键命令。新建一个CustomCommand 类,在其中加入如下代码定义ChangeFontColor 命令。

using System.Windows.Input;

namespace WpfUserControlTest
{
    class CustomCommand
    {
        public static readonly RoutedUICommand ChangeFontColor = 
            new RoutedUICommand("Change Font Color", "ChangeFontColor", typeof(MainWindow));
    }
}

在MainWindow.xaml <Window> 中加入命名空间,以便后面调用ChangeFontColor 命令。

xmlns:c="clr-namespace:WpfUserControlTest"

在<Window.InputBindings>中为ChangeFontColor 添加快捷键组合。

<KeyBinding Modifiers="Control+Alt" Key="C" Command="c:CustomCommand.ChangeFontColor"/>

在<Window.CommandBindings>中添加CanExecute、Excuted 命令事件。

<CommandBinding Command="c:CustomCommand.ChangeFontColor"
                CanExecute="CommandBinding_Color_CanExecute"
                Executed="CommandBinding_Color_Executed"/>

当用户点击“Ctrl+Alt+C”是触发命令事件,最近改变字体颜色。

private void CommandBinding_Color_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

private void CommandBinding_Color_Executed(object sender, ExecutedRoutedEventArgs e)
{
    Random rd = new Random();    
    textBlock1.Foreground = new SolidColorBrush(
        Color.FromRgb(
            (byte)rd.Next(0,255),
            (byte)rd.Next(0, 255),
            (byte)rd.Next(0, 255))
            );
}


以上是关于【WPF】Command 自定义命令的主要内容,如果未能解决你的问题,请参考以下文章

wpf----命令(Command)

潜移默化学会WPF--Command(命令)学习 - AYUI框架 - 博客园

从命令提示符使用自定义命令参数运行 WPF 应用程序

VsCode自定义快捷键,一次运行两个或多个Command命令

VsCode自定义快捷键,一次运行两个或多个Command命令

WPF利用依赖属性和命令编写自定义控件