【问题标题】:Multiple Binding updates from ViewModel来自 ViewModel 的多个绑定更新
【发布时间】:2015-02-24 04:04:37
【问题描述】:

我有一个 MVVM 模型

查看

<StatusBar>
<StatusBarItem>
<TextBlock Text="{Binding Status, UpdateSourceTrigger=PropertyChanged}" Width="Auto"/>
</StatusBarItem>
</StatusBar>

视图模型

ViewModel()
{
    public string Status { get; set; }

    void UpdateProcess()
    {
         UpdateStatus("Updating Database");
         Thread.Sleep(TimeSpan.FromSeconds(5));
         UpdateStatus("Database updated");
    }


    void UpdateStatus(string message)
    {
         Status = message;
         OnPropertyChanged("Status");
    }
}

应用程序运行时,在“更新数据库”之后只显示“更新数据库”而不是“更新数据库”。 似乎只有在 UpdateProcess 方法运行后视图才会更新

我需要在属性更改后立即更新视图。这可能吗?

即使我逐步调试代码,UI 在通过第一个 OnPropertyChanged 时也不会更新。整个 UpdateProcess() 完成后,UI 将更改为“数据库已更新”。

【问题讨论】:

  • 如果没有真正的代码示例,很难知道您在这里实际要求的是什么。如果您像这样连续使用两条消息逐字更新Status 属性,即使您强制UI 在两次更新之间进行更新,用户也不会注意到。这些天电脑太快了。你的实际情况是什么?您要解决什么具体问题?
  • 您是否希望 Message1 闪烁一秒钟?例如,您需要实现一个计时器。否则,在我看来,它正在按预期工作。你预计会发生什么?
  • 使线程进入睡眠状态。它仍然没有按我的预期运行。 @user2588666
  • @Shorn,Sleeping会阻塞UI线程,意味着永远不会渲染更新; UI 将在 5 秒内无响应。如果您想在后台运行时更新 UI,您需要使用某种异步处理机制并将您的状态更新分派到 UI 线程。

标签: c# wpf mvvm


【解决方案1】:

我认为问题在于您试图在长时间运行的操作期间显示状态消息,但它们没有显示出来。这很可能是因为您的长时间运行的操作正在(并因此阻塞)UI 线程上执行。当 UI 线程被阻塞时,UI 上的任何内容都不会更新;事实上,如果您被阻止的时间足够长,Windows 会向用户建议您的应用程序已停止响应并应该关闭。

如果您使用带有 async/await 的 C# 版本,您可以执行以下操作:

    private async Task UpdateProcess()
    {
        UpdateStatus("Updating Database");
        await Task.Run(UpdateDatabaseMethod);
        UpdateStatus("Database updated");
    }

    private void UpdateDatabaseMethod()
    {
        //Do long-running stuff in background...
        //Note that this will no longer be executing in the UI thread
        //so you may need to watch out for thread safety issues that you could previously ignore
        //This might mean adding some locks around your database access methods...
    }

对于异步/等待支持之前的版本,请查看BackgroundWorker

需要注意的是,您现在正在后台线程中运行长时间运行的任务,这与阻塞 UI 时的行为不同。这可能会带来许多新的挑战和令人头疼的问题,但不幸的是,如果您想将 UI 与长时间运行的任务并行运行,这将是一个必要的弊端。

其他问题包括用户现在可以在更新数据库时单击其他内容。如果您需要阻止 UI 交互,则需要一些其他机制来禁用可能在您的长时间运行操作进行时干扰的控件。一种典型的方法是某种“忙碌指示器”对话框,其中包含类似这样的状态消息。

【讨论】:

    【解决方案2】:

    一旦内部值更改,您可以扩展 Status 属性的设置器以提高 PropertyChanged

    private string _status;
    public string Status
    {
      get
      {
        return _status;
      }
      set
      {
        _status = value;
        OnPropertyChanged("Status");
      }
    }
    

    然后会发生的是,当您设置 Status 属性时,PropertyChanged 将触发并通知 UI 更新该字段。

    这是 WPF 知道从绑定中更新控件值的唯一方法,而不是在创建控件之后。

    可能有影响的是绑定的模式。

    <StatusBar>
      <StatusBarItem>
        <TextBlock Text="{Binding Status, UpdateSourceTrigger=PropertyChanged}, Mode=TwoWay" Width="Auto"/>
      </StatusBarItem>
    </StatusBar>
    

    您可以查看here 以查看对该模式的更好描述

    【讨论】:

      猜你喜欢
      • 2017-11-08
      • 1970-01-01
      • 2018-12-20
      • 1970-01-01
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 2018-01-16
      • 2023-03-12
      相关资源
      最近更新 更多