MainWindow.xaml
<Window x:Class="CommunityToolkit.MVVM_RelayCommand_测试.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:CommunityToolkit.MVVM_RelayCommand_测试"mc:Ignorable="d"Title="MainWindow" Height="150" Width="200"><StackPanel><Button Width="150" Height="30" Margin="0 30 0 0" Command="{Binding IncrementCounterCommand}" >click</Button><TextBlock Width="150" Height="30" Text="{Binding Counter}"></TextBlock></StackPanel> </Window>
MainWindow.cs
using System.Diagnostics.Metrics; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes;namespace CommunityToolkit.MVVM_RelayCommand_测试
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
}
MainWindowViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System; using System.Collections.Generic; using System.Diagnostics.Metrics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input;namespace CommunityToolkit.MVVM_RelayCommand_测试
{
internal partial class MainWindowViewModel:ObservableObject
{
[ObservableProperty]
private int _counter;
public RelayCommand IncrementCounterCommand { get; }</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> IncrementCounter(){Counter</span>++<span style="color: #000000;">;IncrementCounterCommand.NotifyCanExecuteChanged(); //注意这里是关键} </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> MainWindowViewModel(){IncrementCounterCommand </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> RelayCommand(IncrementCounter, CanExecute);}</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">bool</span><span style="color: #000000;"> CanExecute(){ </span><span style="color: #0000ff;">return</span> Counter <= <span style="color: #800080;">3</span><span style="color: #000000;">;} }
}
1、初步使用 CommunityToolkit.MVVM 中的RelayCommand
2、通过属性的变更来改变按钮的状态。
以下是deepseek的纠错信息:
你的代码中,按钮的 IsEnabled
绑定到了 IncrementCounterCommand.CanExecute
,但这里存在几个问题:
问题分析:
-
RelayCommand.CanExecute
不是一个可绑定的属性
RelayCommand
的CanExecute
是一个方法(通过ICommand.CanExecute
实现),而不是一个可绑定的属性(如INotifyPropertyChanged
属性)。因此,当CanExecute()
的返回值改变时,UI 无法自动收到通知。 -
没有通知机制更新按钮状态
当Counter
改变时,你需要手动调用IncrementCounterCommand.NotifyCanExecuteChanged()
,这样按钮才会重新查询CanExecute()
方法并更新状态(启用/禁用)。但你的代码中并没有在Counter
改变时触发通知。
解决方案:
方案1:使用 [RelayCommand]
特性(推荐)
CommunityToolkit.Mvvm 提供了 [RelayCommand]
特性,可以自动生成命令,并支持自动通知 CanExecute
变化。你只需要在方法上添加 [RelayCommand]
并指定 CanExecute
方法名即可。
修改 MainWindowViewModel.cs
:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows.Input;namespace CommunityToolkit.MVVM_RelayCommand_测试
{
internal partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private int _counter;// 使用 [RelayCommand] 特性自动生成命令,并指定 CanExecute 方法
[RelayCommand(CanExecute = nameof(CanExecute))]
private void IncrementCounter() => Counter++;private bool CanExecute() => Counter <= 3;// 当 Counter 改变时,通知命令的 CanExecute 可能已改变
partial void OnCounterChanged(int value)
{
// 通知命令重新检查 CanExecute
IncrementCounterCommand.NotifyCanExecuteChanged();
}
}
}
方案2:手动调用 NotifyCanExecuteChanged
如果你不想使用特性,可以在 Counter
的 setter 中手动通知命令状态变化(但你已经使用了 [ObservableProperty]
,所以可以通过部分方法 OnCounterChanged
来实现)。
修改 XAML 绑定:
你不需要绑定 IsEnabled
,因为 ICommand
本身就会控制按钮的启用状态。只需移除 IsEnabled
绑定:
<Button Width="150" Height="30" Margin="0 30 0 0"
Command="{Binding IncrementCounterCommand}">click</Button>
总结:
- 使用
[RelayCommand]
特性简化命令定义。 - 在
Counter
变化时调用NotifyCanExecuteChanged()
。 - 不需要手动绑定
IsEnabled
,因为ICommand
会自动管理按钮状态。
修改后,当 Counter
超过 3 时,按钮会自动禁用(变为灰色)。