请参阅代码示例。启动时,CanExecuteButtonClick 方法将被评估一次。执行 CanExecuteButtonClick 方法时,将评估 CanClick 属性。我手动引发 Command ButtonClick 的 CanExecuteChanged 事件。
通过调试器,我看到调用了 RaiseCanExecuteChanged 方法,但返回了实现 null-check if Guard 的位置。
因此,UI 显然没有更新,因为事件不会重新评估相应的 CanExecute 方法。
寻找互联网和其他资源(例如copilot)尚未产生任何有用的结果。有没有人遇到过这个问题,或者如果我在实施过程中犯了错误,可以给我一些反馈吗?
如果我自己发现任何事情,我会更新这个帖子。谢谢!
这是 ICommand 的(标准)实现,我是如何在我的项目中实现它的。我实现了 RaiseCanExecuteChanged 方法,灵感来自于这篇 stackoverflow 文章。
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged == null) return;
CanExecuteChanged(this, EventArgs.Empty);
}
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
}
我像这样实现了我的命令: XAML:
<Button Content="Click me"
Command="{x:Bind ViewModel.ButtonClick}">
视图模型:
public RelayCommand ButtonClick => new RelayCommand((obj) => ExecuteButtonClick(null), (obj) => CanExecuteButtonClick(null));
private async Task ExecuteButtonClick(object commandParameter)
{
//Some code
}
private bool CanExecuteButtonClick(object commandParameter) => CanClick;
//Another command, for simplicity only the execute method
private async Task ExecuteAnotherButtonClick(object commandParameter)
{
//Some code
CanClick = true;
ButtonClick.RaiseCanExecuteChanged();
}
可能不是您问题的直接答案,但让我向您展示一些使用 CommunityToolkit.Mvvm NuGet 包的示例代码。您将能够避免一堆样板代码:
// This class needs to be "partial" for the source generators.
public partial class SomeViewModel : ObservableObject
{
// The source generator will generate a "IsReady" property for you.
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(DoSomethingCommand))]
private bool _isReady;
public bool CanDoSomething() => IsReady;
// The source generator will generate a "DoSomethingCommand" for you.
[RelayCommand(CanExecute = nameof(CanDoSomething))]
private async void DoSomething()
{
}
}
<ToggleSwitch IsOn="{x:Bind ViewModel.IsReady, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button
Command="{x:Bind ViewModel.DoSomethingCommand}"
Content="Do something" />