【问题标题】:Async MVVM - how to change NotifyTaskCompletion.Result异步 MVVM - 如何更改 NotifyTaskCompletion.Result
【发布时间】:2016-08-25 16:15:11
【问题描述】:

我的问题来自 Stephen Cleary 的an article

基本上是有标签的

<Label Content="{Binding UrlByteCount.Result}"/>

它是由 viewmodel c.tor 设置的

UrlByteCount = new NotifyTaskCompletion<int>(
                MyStaticService.CountBytesInUrlAsync("http://www.example.com"));

到目前为止一切顺利。 现在我做一个微不足道的改变:

 UrlByteCount = new NotifyTaskCompletion<int>(MyStaticService.ImmediateSet(-1));

已经定义

public static Task<int> ImmediateSet(int res)
{
    var tcs = new TaskCompletionSource<int>();
    tcs.SetResult(res);
    return tcs.Task;
}

显然标签立即显示-1。 好的,那我添加一个带有viewmodel命令绑定的按钮,因为我想在点击按钮的时候设置标签

跳过所有礼仪部分(委托命令等),核心功能又是:

private void TestLogic()
{
    UrlByteCount = new NotifyTaskCompletion<int>( // FIX ME
        MyStaticService.CountBytesInUrlAsync("http://www.example.com")); // FIX ME
}

我完全知道它不起作用并且标签的内容将保持 -1,但我想问哪种方法是解决此问题的最佳方法?

问题的第二部分。

假设您已经找到了第一部分的解决方案并且点击按钮异步更改了标签的内容(保持ui响应性),您能否确认以下代码是否是防止“双击”的一致方式(即“多次执行”)?

private async void TestLogic()
{
    canRun = false;
    ((DelegateCommand)TestCommand).RaiseCanExecuteChanged();
    await FoundASolution();
    canRun = true;
    ((DelegateCommand)TestCommand).RaiseCanExecuteChanged();
}

private async Task<int> FoundASolution()
{
    await Task.Delay(TimeSpan.FromSeconds(10));
    return 21;
}

【问题讨论】:

  • 为什么它不起作用?如果您在 UrlByteCount 的设置器中引发属性更改事件,它应该可以正常工作。
  • @Evk 我假设它,因为绑定是“UrlByteCount.Result”而不是“UrlByteCount”,所以我认为做 UrlByteCount = new 不干净......不是吗破坏指向.Result的指针?顺便说一句,是的,我看到它确实有效
  • 不,当您为 UrlByteCount 分配新值时,绑定知道它已更改(当然假设您引发属性更改事件),即使绑定路径是 UrlByteCount.Whatever1.Whatever2...
  • @Evk 好的,请回答问题。谢谢!
  • 为什么现在投反对票?如果您因为认为在 UrlByteCount 上提出更改的属性很重要而对我的问题投反对票,则无需这样做。绑定到常规字符串属性更加标准,并且确实有效。 => 看看我的answer(以及我的meta 问题,如果没有被删除)

标签: c# wpf mvvm async-await


【解决方案1】:

假设您在 UrlByteCount 设置器中引发属性更改事件,您的代码应该可以正常工作。您绑定到 UrlByteCount.Result 的事实并不意味着当您仅更改 UrlByteCount 时绑定不会刷新 - 它会。

至于您的第二部分 - 在开始长时间运行操作之前,可以通过将 Command.CanExecute 设为 false 并通过 Command.CanExecuteChanged 事件通知这一点来禁用按钮。即使操作因异常而失败,只要确保您再次启用它(因此包装在 try-finally 块中)。您可能希望通知用户有关错误并允许他修复它(或者稍等一下,例如,如果错误是网络故障),然后重试操作,这在您的情况下是不可能的 - 按钮将保持禁用以防万一错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2017-11-01
    • 1970-01-01
    • 2022-11-30
    相关资源
    最近更新 更多