• 【wpf】Command Binding 命令绑定的使用


    前言

    这次讲解的命令绑定,主要解决的问题是,为实现MVVM模式进行铺垫,实现前后台逻辑的解耦。

    我们知道如果Button直接实现Click事件,那么实现的逻辑必然在Window后台代码中,为了实现MVVM,我要将业务逻辑放在ViewMode里面,这时需要Command Binding。

    Command Binding

    使用Command 替换 Click

    前台代码:

    1. <Button Grid.Row="2"
    2. Command="{Binding BtnSaveCommand}"
    3. CommandParameter="{Binding RelativeSource={RelativeSource Self}}">保存Button>

    创建CommandBase类

    然后创建CommandBase类,该类实现ICommand接口。

    ICommand需要实现一个事件:CanExecuteChanged

    两个方法: Execute, CanExecute

    Execute 是命令促发后,系统会调用的回调函数

    CanExecute 是当CanExecuteChanged事件触发后,体统会调用它,并更具它的返回值判断控件是否可用。

    1. public class CommandBase : ICommand
    2. {
    3. public event EventHandler CanExecuteChanged;
    4. public Action<object> DoExecute { get; set; }
    5. // 这里给个默认的值,不实现就返回true
    6. public Func<object, bool> DoCanExecute { get; set; } = new Func<object, bool>(obj => true);
    7. public bool CanExecute(object parameter)
    8. {
    9. // 让实例去实现这个委托
    10. return DoCanExecute?.Invoke(parameter) == true;// 绑定的对象 可用
    11. }
    12. public void Execute(object parameter)
    13. {
    14. // 让实例去实现这个委托
    15. DoExecute?.Invoke(parameter);
    16. }
    17. //目的 就是触发一次CanExecuteChanged事件
    18. public void DoCanExecuteChanged()
    19. {
    20. // 触发事件的目的就是重新调用CanExecute方法
    21. CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    22. }
    23. }

    ViewMode中实例化命令

    1. public CommandBase BtnSaveCommand { get; set; }
    2. public ConfigInfoViewMode()
    3. {
    4. BtnSaveCommand = new CommandBase()
    5. {
    6. DoExecute = new Action<object>(SaveTo),
    7. DoCanExecute = new Func<object, bool>(CanSave)
    8. };
    9. }
    10. //最终按钮会触发到改函数
    11. void Save(object obj)
    12. {
    13. }
    14. //决定按键是否可用(这也是命令额外的一个作用)
    15. // 通过调用DoCanExecuteChanged,可以触发该元素
    16. public bool CanSave(object obj)
    17. {
    18. return true;
    19. }

    事件触发

    1. //目的 就是触发一次CanExecuteChanged事件
    2. public void DoCanExecuteChanged()
    3. {
    4. // 触发事件的目的就是重新调用CanExecute方法
    5. CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    6. }

    触发事件的目的就是重新调用CanExecute方法,从而从新判断控件是否可用。

    但是这个DoCanExecuteChanged(),是需要我们人为调用的。

    CommandManager

    另外一种写法可以让系统去调用,我们需要一个新的知识点CommandManager

    以下两种写法都可以,只需要在定义CanExecuteChanged时稍微改动一下:

    1. // 通知:当前按钮检查可用条件 触发 一次CanExecute
    2. // 写法一
    3. public event EventHandler? CanExecuteChanged
    4. {
    5. add { CommandManager.RequerySuggested += value; }
    6. remove { CommandManager.RequerySuggested -= value; }
    7. }
    8. //写法二
    9. public event EventHandler? CanExecuteChanged
    10. {
    11. add => CommandManager.RequerySuggested += value;
    12. remove => CommandManager.RequerySuggested -= value;
    13. }

    这里的意思是,通过静态变量CommandManager将CanExecuteChanged挂载到,RequerySuggested 这个事件上,这里的value是指CanExecuteChanged本身,下图可以证明。(这个和属性的value有着异曲同工之妙)

     从此之后,这个检测工作交给系统。

    我发现这个检测的时机其实和绑定有关。

    1. <TextBox Text="{Binding mainModel.Value1,UpdateSourceTrigger=PropertyChanged}"/>
    2. <TextBox Text="{Binding mainModel.Value3}"/>

    我们在检擦函数中这么写的:

    1. // Hello命令的的可用判断逻辑
    2. public bool CanHello(object obj)
    3. {
    4. // 命令可用条件
    5. // 当调用 CanExecuteChanged 事件后,重新进行条件检查
    6. return this.mainModel.Value1 != 0;
    7. }
    8. public bool CanWorld(object obj)
    9. {
    10. return this.mainModel.Value3 != 0;
    11. }

    也就是说,TextBox中的值会决定Button是否可用!

    那么第一个TextBox的值,只要一发生改变,那么就会触发检查是否可用,而第二个TextBox只有

    失去焦点的时候,才会触发检查。

    这里有个小疑问,我们的Command是写在Button上的,所以判断是Button是否可用,同时Command实现了CanExecuteChanged事件,并挂载到了全局,以便系统调用,那系统是怎么知道

    变化的Value和Button的关系的呢?也不知道微软是什么时候将这个指和Button关联上的

    强制触发

    当然,此时如果你觉得你想在某个时刻进行强制触发检测,也是可以的,还是使用CommandManager这个静态变量:

    CommandManager.InvalidateRequerySuggested();

    鼠标和键盘

    写道这里,其实还存在一个问题,Button的Command是由但是触发的,如果我想通过双击或者快捷键触发怎么办呢?

    InputBindings

    InputBindings,满足你的需求:

    1. <Button Content="Button">
    2. <Button.InputBindings>
    3. <MouseBinding MouseAction="LeftDoubleClick"
    4. Command="{Binding Btn1Command}"
    5. CommandParameter="123"/>
    6. <KeyBinding Key="Q" Modifiers="Alt"
    7. Command="{Binding Btn1Command}"
    8. CommandParameter="123"/>
    9. Button.InputBindings>
    10. Button>

    MouseBinding 中的MouseAction还有如下操作: 

    • 单击鼠标左键 :LeftClick
    • 双击鼠标左键:LeftDoubleClick
    • 单击鼠标中键 :MiddleClick
    • 双击鼠标中键:MiddleDoubleClick
    • 单击鼠标右键:RightClick
    • 双击鼠标右键:RightDoubleClick
    • 不执行任何操作:None
    • 旋转鼠标滚轮:WheelClick

    KeyBinding 

    KeyBinding 可以帮我们实现快捷键和快捷键组合,简直完美~~。

  • 相关阅读:
    Tomcat
    借车、挂靠风险有多大?
    首次公开!赛迪顾问《湖仓一体技术研究报告》深入解读
    C++:优先级队列模拟实现和仿函数的概念使用
    什么是Docker
    12096 - The SetStack Computer (UVA)
    C++学习记录——삼십이 C++IO流
    贪心算法的概念与使用
    多版本node的安装与切换详细操作
    DHCP动态主机配置协议_组网实验
  • 原文地址:https://blog.csdn.net/songhuangong123/article/details/126317592