ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

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

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

返回列表