zoukankan      html  css  js  c++  java
  • 【WPF】Command 自定义命令

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

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

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

    方法一 从头开始创建自定义命令

    第一步:创建命令

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

        class CustomCommand : ICommand
        {
            //当能不能做发生变化时会触发的事件(必须要实现)
            public event EventHandler CanExecuteChanged;
    
            public void Execute(object param)  //做什么(必须要实现)
            {
                ExecuteAction?.Invoke(param);
            }
    
            public bool CanExecute(object param)  //能做吗(必须要实现)
            {
                if (CanExecuteAction != null)
                    return CanExecuteAction(param);
                return false;
            }
    
            public Action<object> ExecuteAction { get; set; }
            public Func<object, bool> CanExecuteAction { get; set; }
        }
    

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

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

    第二步:完成ViewModel

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

    //先实例化这个命令(这是属于ViewModel的命令,等下要被送到View中去)
    public CustomCommand MyCommand { get; set; }
    
    public void DoSomething(object param){
        //这个命令真正要做的事情
    }
    public bool CanDoSomething(object param){
        return true;  //判断能否做这个事情,大部分时候返回true就行了
    }
    public MyViewModel(){
        //在ViewModel的构造函数中,完成对命令的设置
        MyCommand = new CustomCommand();
        MyCommand.ExecuteAction = new Action<object>(this.DoSomething);
        MyCommand.CanExecuteAction = new Func<object, bool>(this.CanDoSomething);
    }
    

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

    第三步:完成View

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

    先要加入命名空间,才能获得我们的 ViewModel。这里把命名空间设为vm
    <Window xmlns:vm="clr-namespace:MyApp.ViewModel" ... />
        <Grid>
            <Grid.DataContext>
                <vm:MyViewModel>  <!--把第二步中的ViewModel当作DataContext-->
            </Grid.DataContext>
    
            <Button Content="Click here" Command="{Binding MyCommand}" />
        </Grid>
    </Window>
    

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

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

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


    方法二 使用自带的 RoutedUICommand

    先创建一个命令:

    public static class CustomCommands
    {
        public static readonly RoutedUICommand ExitCommand = new RoutedUICommand(
            "quit app", 
            "ExitCommand",
            typeof(CustomCommands),
            new InputGestureCollection() { 
                new KeyGesture(Key.W, ModifierKeys.Control)  //可以为它绑定快捷键
            });
    }
    

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

    public void ExitCommand_Execute(object sender, ExecutedRoutedEventArgs e)
    {
        //在这里写执行命令的具体内容(要做什么事)
        e.Handled = true;
    }
    public void ExitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;  //在这里判断该命令能否执行
        e.Handled = true;
    }
    

    最后在 xaml 里面进行绑定:

    <Window.CommandBindings>
        <CommandBinding Command="local:CustomCommands.ExitCommand" 
            CanExecute="ExitCommand_CanExecute" 
            Executed="ExitCommand_Execute"/>
    </Window.CommandBindings>
    
    <Button Content="Exit" Command="local:CustomCommands.ExitCommand"/>
    
     
     
    0人点赞
     
    C#
     
     


    作者:Hemmelfort
    链接:https://www.jianshu.com/p/6ca3cde0b5ee
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    Java 蓝桥杯 算法训练 貌似化学
    Java 蓝桥杯 算法训练 貌似化学
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    JAVA-蓝桥杯-算法训练-字符串变换
    Ceph:一个开源的 Linux PB 级分布式文件系统
    shell 脚本监控程序是否正在执行, 如果没有执行, 则自动启动该进程
  • 原文地址:https://www.cnblogs.com/javalinux/p/14600041.html
Copyright © 2011-2022 走看看