C# WPF CommunityToolkit.MVVM (測試一)
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; }
private void IncrementCounter()
{
Counter++;
IncrementCounterCommand.NotifyCanExecuteChanged();
}
public MainWindowViewModel()
{
IncrementCounterCommand = new RelayCommand(IncrementCounter, CanExecute);
}
private bool CanExecute()
{
return Counter <= 3;
}
}
}
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 時,按鈕會自動禁用(變為灰色)。

浙公網安備 33010602011771號