C# WPF 命令机制(关闭CanExecute自动触发,改手动)

在绑定数据变化时手动触发UI状态检查

xml 复制代码
<Window x:Class="WpfApp5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp5"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button Content="点击"  
                Command="{Binding ClickCommand}"  
                Margin="10" Padding="15" />
        <Button Content="Sub"  
        Command="{Binding ClickCommandSub}"  
        Margin="10" Padding="15" />
        <TextBlock Text="{Binding Count, StringFormat='已点击次数: {0}'}"  
                   HorizontalAlignment="Center" Width="80" Margin="10"/>
    </StackPanel>
</Window>
csharp 复制代码
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}



public class ManualRelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public ManualRelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
    public void Execute(object parameter) => _execute(parameter);

    // 手动触发事件  
    public event EventHandler CanExecuteChanged;
    public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);

    //public event EventHandler CanExecuteChanged
    //{
    //    add => CommandManager.RequerySuggested += value;
    //    remove => CommandManager.RequerySuggested -= value;
    //}

     同时保留手动触发方法  
    //public void ForceRaiseCanExecuteChanged() => CommandManager.InvalidateRequerySuggested();
}

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));


    private int _count;
    public int Count
    {
        get => _count;
        set
        {
            if (_count == value) return;
            _count = value;
            OnPropertyChanged();
            // 手动触发命令状态更新  
            ClickCommand.RaiseCanExecuteChanged();
        }
    }

    public ManualRelayCommand ClickCommand { get; }
    public ICommand ClickCommandSub
    {
        get { return new ManualRelayCommand(_ => Count--, _ => true); }
        set { }
    }

    public MainViewModel()
    {
        ClickCommand = new ManualRelayCommand(
            ClickEvent,
           _CanExecute 
        );
    }
    private void ClickEvent(object obj)
    {
        Count++;
    }

    private bool _CanExecute(object arg)
    {
        return Count < 3;
    }
}
相关推荐
淡海水32 分钟前
【原理】Struct 和 Class 辨析
开发语言·c++·c#·struct·class
淡海水36 分钟前
【原理】Unity GC 对比 C# GC
unity·c#·gc·垃圾回收
张人玉1 小时前
C#读取文件, IO 类属性及使用示例
microsoft·c#
咕白m6256 小时前
通过 C# 高效提取 PDF 文本的完整指南
后端·c#
hqwest9 小时前
C#WPF实战出真汁08--【消费开单】--餐桌面板展示
c#·wpf·ui设计·wpf界面设计
orangapple9 小时前
WPF 打印报告图片大小的自适应(含完整示例与详解)
c#·wpf
★YUI★1 天前
学习游戏制作记录(玩家掉落系统,删除物品功能和独特物品)8.17
java·学习·游戏·unity·c#
谷宇.1 天前
【Unity3D实例-功能-拔枪】角色拔枪(二)分割上身和下身
游戏·unity·c#·游戏程序·unity3d·游戏开发·游戏编程
LZQqqqqo1 天前
C# 中 ArrayList动态数组、List<T>列表与 Dictionary<T Key, T Value>字典的深度对比
windows·c#·list
Dm_dotnet1 天前
Stylet启动机制详解:从Bootstrap到View显示
c#