【问题标题】:Button state is not updated using RelayCommand未使用 RelayCommand 更新按钮状态
【发布时间】:2016-05-04 10:52:22
【问题描述】:

我的应用程序正在使用 MVVM Light 工具包。这是与 XAML 中的按钮绑定的命令:

    private RelayCommand _buttonCommandNew;
    public RelayCommand ButtonCommandNew
    {
        get
        {
            var worker = new TCService();
            return _buttonCommandNew
                   ?? (_buttonCommandNew = new RelayCommand(async () =>
                   {
                       var progress = new Progress<string>(status =>
                       {
                           ProgressText = status;
                       });

                       await worker.GenerateConfiguration(1, "", "", progress);
                   }, () => !worker.InProgress
                ));
        }
    }

这是服务:

class TCService : ITCService
{
    public Task<bool> GenerateConfiguration(int cellCount, string templateFilePath, string outputFilePath, IProgress<string> progress)
    {
        return Task.Run(() => RunConfigurator(progress));
    }

    public bool InProgress { get; private set; }

    private bool RunConfigurator(IProgress<string> progress)
    {
        InProgress = true;
        Thread.Sleep(6000);
        progress.Report("Yeah!");
        InProgress = false;
        return true;
    }
}

我想要实现的是在服务开始工作时禁用按钮并在最后启用它。当前的实现不会发生这种情况。更重要的是,要遵守 MVVM Light。我觉得我的服务应该继承自 MVVM Light 中的一个基类,并且我需要使用 Set 来通知 UI 有关更改。但不确定我的方向是否正确。

【问题讨论】:

    标签: c# wpf xaml mvvm-light


    【解决方案1】:

    您可以将InProgress 属性移动到视图模型(包含ButtonCommandNew 属性的类)并绑定到UI。

    然后,在InProgress 属性的设置器中,您可以调用ButtonCommandNew.RaiseCanExecuteChanged,这将通知UI 在_buttonCommandNew RelayCommand 上调用CanExecute,从而启用或禁用按钮UI 取决于 InProgress 属性的值。

    在这种情况下,您需要在调用worker.GenerateConfiguration 之前将InProgress 属性设置为true,然后在调用完方法后将其重置为false

    【讨论】:

    • 是的,这成功了,但我认为 CanExecute 可以通过 RelayCommand 以某种方式观察到,我只需要使用 Set 传播更改。
    • UI 观察到来自 ICommand 的 CanExecuteChanged 事件,一旦引发该事件,UI 将重新查询 CanExecute 以确定是否启用或禁用按钮(或绑定到命令的任何内容)。
    • 我仍然想了解为什么它不能“开箱即用”。这是响应命令执行而启用/禁用按钮的非常常见的模式。 CanExecuteChanged 是由 RaiseCanExecuteChanged 提出的,这很清楚。但在我看来,应该观察canExecute 本身的变化。在 src 代码中的 RelayCommand 之上,我看到以下注释:IMPORTANT: Note that closures are not supported at the moment due to the use of WeakActions。你觉得有关系吗?
    • 这是 WPF 人员设计它的工作方式,您提出 CanExecuteChanged 以通知源(通常是 UI)有关命令执行能力的更改。源通过调用 CanExecute 确定执行能力,然后更新其用户交互能力。我不认为对闭包的支持与此有关,因为 ICommand 合同与您是使用 MVVM Light 中的 RelayCommand 还是使用 ICommand 接口的任何其他实现无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    相关资源
    最近更新 更多