当前位置: 首页 > news >正文

WPF学习笔记(24)命令与ICommand

命令与ICommand

  • 一、命令
    • 1. ICommandSource
    • 2. 示例
    • 3. CommandBinding
  • 二、ICommand
    • 1.ICommand接口
    • 2. ICommand用法
    • 3. CanExecute
  • 总结


一、命令

在这里插入图片描述
官方文档:https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/commanding-overview

1. ICommandSource

在这里插入图片描述
官方文档:https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/how-to-implement-icommandsource

在这里插入图片描述

2. 示例

在这里插入图片描述
在这里插入图片描述

    <Grid><TextBox x:Name="textBox" Text="TextBox" VerticalAlignment="Top"  Height="150" Margin="219,35,187,0"/><Button x:Name="buttonCut"Content="剪切"Command="ApplicationCommands.Cut"CommandTarget="{Binding ElementName=textBox}"Height="100" Margin="219,233,419,102"/><Button x:Name="buttonPaste"Content="粘贴"Command="ApplicationCommands.Paste"CommandTarget="{Binding ElementName=textBox}" Margin="453,233,187,107"/></Grid>

在这里插入图片描述

3. CommandBinding

在这里插入图片描述
在这里插入图片描述

  • 当TEXTBOX内容长度大于0时,CanExecute被判断为true
  • true可以启用命令源按钮,false禁用按钮
    在这里插入图片描述
<Window.CommandBindings><CommandBinding Command="ApplicationCommands.Cut" CanExecute="my_CanExecute" Executed="my_Execute"/>
</Window.CommandBindings><Grid><TextBox x:Name="textBox" Text="TextBox" VerticalAlignment="Top"  Height="150" Margin="219,35,187,0"/><Button x:Name="buttonCut" Margin="219,233,419,102" Height="100" Content="剪切"Command="ApplicationCommands.Cut"/><Button x:Name="buttonPaste"Content="粘贴"Command="ApplicationCommands.Paste"CommandTarget="{Binding ElementName=textBox}"Margin="453,233,187,107"/>
</Grid>
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private void my_Execute(object sender, ExecutedRoutedEventArgs e){Console.WriteLine("Execute!!!");textBox.Cut();}private void my_CanExecute(object sender, CanExecuteRoutedEventArgs e){e.CanExecute = textBox.SelectionLength > 0;}
}

二、ICommand

在这里插入图片描述

官方文档:https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.input.icommand?view=net-9.0

1.ICommand接口

在这里插入图片描述

ICommand接口的属性与事件如下:
在这里插入图片描述

2. ICommand用法

在这里插入图片描述

    <Grid><TextBox HorizontalAlignment="Left" Margin="222,62,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="422" Height="102"/><Button x:Name="button1" Content="  自定义命令" HorizontalAlignment="Left" Margin="222,217,0,0" VerticalAlignment="Top" Height="64" Width="145"/><Button x:Name="button2" Content="触发事件" HorizontalAlignment="Left" Margin="499,217,0,0" VerticalAlignment="Top" Height="64" Width="145"/></Grid>

在MainWindow.xaml.cs文件内自定义命令接口
在这里插入图片描述
在这里插入图片描述

<Window.Resources><local:MyCommand x:Key="MyCMD" />
</Window.Resources>
<Grid><TextBox x:Name="textBox" HorizontalAlignment="Left" Margin="222,62,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="422" Height="102"/><Button x:Name="button1" Content="  自定义命令"Command="{StaticResource MyCMD}"CommandParameter="{Binding ElementName=textBox,Path=Text}"HorizontalAlignment="Left" Margin="222,217,0,0" VerticalAlignment="Top" Height="64" Width="145"/><Button x:Name="button2" Content="触发事件" HorizontalAlignment="Left" Margin="499,217,0,0" VerticalAlignment="Top" Height="64" Width="145"/>
</Grid>
public class MyCommand : ICommand
{public event EventHandler CanExecuteChanged;public bool CanExecute(object parameter){return true;//按钮可以点击//return false;//按钮不可点击}//Execute方法中实现命令处理逻辑public void Execute(object parameter){MessageBox.Show(parameter.ToString());}
}

以下为CanExecuteChanged的事件解释:
在这里插入图片描述

public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private void button2_Click(object sender, RoutedEventArgs e){MyCommand c = Resources["MyCMD"] as MyCommand;//触发CanExecuteChangedc.RaiseCanExecuteChanged();}
}
//实现ICommand接口
public class MyCommand : ICommand
{public event EventHandler CanExecuteChanged;public bool CanExecute(object parameter){String str = parameter as String;return str?.Length > 0;//return true;//按钮可以点击//return false;//按钮不可点击}//Execute方法中实现命令处理逻辑public void Execute(object parameter){MessageBox.Show(parameter.ToString());}//定义一个方法,手动触发CanExecuteChanged事件public void RaiseCanExecuteChanged() {//表面上,没有为 CanExecuteChanged 这个事件添加任何订阅方法//例如CanExecuteChanged += fun;//但是我们为按钮设置命令时,自动加入了一个此事件订阅的方法,//并且这个订阅的方法,会去调用命令的CanExecute//可通过Delegate查看CanExecuteChanged的来源与内容Delegate[] delegates = CanExecuteChanged.GetInvocationList();//delegates内查看到 System.Windows.Input.CanExecuteChangedEventManager+HandlerSink"//OnCanExecuteChangedCanExecuteChanged?.Invoke(this, EventArgs.Empty);}

加粗样式

3. CanExecute

以ButtonBase为例介绍,调用了OnCommandChanged
在这里插入图片描述
OnCommandChanged调用了HookCommand
在这里插入图片描述

HookCommand调用了AddHandler,CanExecute调用了CanExecuteCommandSource在这里插入图片描述
在这里插入图片描述
AddHandler调用的PrivateAddHandler又new 了一个HandlerSink
在这里插入图片描述

HandlerSink将OnCommandChanged函数添加到Icommand接口的CanExecuteChanged
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

总结

关于ButtonBase、CanExecuteChangedEventManager、commandHelpers的详细原理、我们可以参考WPF框架的源码
https://github.com/dotnet/wpf/blob/main/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/ButtonBase.cs
https://github.com/dotnet/wpf/blob/main/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/CanExecuteRoutedEventArgs.cs
https://github.com/dotnet/wpf/blob/main/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Commands/CommandHelpers.cs

http://www.dtcms.com/a/267545.html

相关文章:

  • LeetCode 第91题:解码方法
  • 二叉树题解——二叉搜索树中第 K 小的元素【LeetCode】使用外部变量ans记录答案
  • C++ 网络编程(15) 利用asio协程搭建异步服务器
  • 【大模型】到底什么是Function Calling和MCP,以及和ReAct推理的关系是什么?
  • [学习] 深入理解 POSIX
  • 面试150 最长连续序列
  • Node.js worker_threads深入讲解教程
  • 【LeetCode102.二叉树的层序遍历】vs.【LeetCode103.二叉树的锯齿形层序遍历】
  • Apollo自动驾驶系统中Planning模块的架构设计与核心逻辑解析(流程伪代码示例)
  • 45-使用scale实现图形缩放
  • 探索 .NET 桌面开发:WinForms、WPF、.NET MAUI 和 Avalonia 的全面对比(截至2025年7月)
  • 炼丹炉 TD-trainer 的安装与部署,LoRA、dreambooth
  • <三>Sping-AI alibaba 文生图
  • Cursor/VScode ,点击运行按钮,就打开新的终端,如何设置为在当前终端运行文件而不是重新打开终端----一招搞定篇
  • 数字孪生技术引领UI前端设计新潮流:虚拟现实的深度集成
  • 在sf=0.1时测试fireducks、duckdb、polars的tpch
  • OpenLayers 设置线段样式
  • 深入学习c++之---AVL树
  • 支持零样本和少样本的文本到语音48k star的配音工具:GPT-SoVITS-WebUI
  • 完成ssl不安全警告
  • DQL-6-分页查询
  • Redis的编译安装
  • PVE DDNS IPV6
  • 超详细yolo8/11-detect目标检测全流程概述:配置环境、数据标注、训练、验证/预测、onnx部署(c++/python)详解
  • Altium Designer使用教程 第一章(Altium Designer工程与窗口)
  • ESXi 8.0 SATA硬盘直通
  • python-字符串
  • 量化可复用的UI评审标准(试验稿)
  • OPENPPP2 VDNS 核心域模块深度解析
  • 电源管理芯片(PMIC) 和 电池管理芯片(BMIC)又是什么?ING