WinUI:ICommand 实现 - CanExecuteChanged 为 null 并且 UI 未刷新

问题描述 投票:0回答:1

请参阅代码示例。启动时,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();
}
mvvm winui-3 icommand
1个回答
0
投票

可能不是您问题的直接答案,但让我向您展示一些使用 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" />
© www.soinside.com 2019 - 2024. All rights reserved.