Wpf绑定更新发生得太晚了

时间:2017-07-08 11:36:48

标签: c# wpf xaml mvvm

我使用MVVM。命令很慢。我想使用日志来指示执行的位置。 XAML:

 <TextBlock Height="200" Text="{Binding Log.Content, UpdateSourceTrigger=PropertyChanged}"></TextBlock>

代码:

Log.addLine("Ledger initialized.");
// slow1 operation
Log.addLine("slow1 operation.");

只有在整个命令完成后才会更新文本块。当GUI处于活动状态时,两条消息都会同时出现。

2 个答案:

答案 0 :(得分:0)

在这个例子中,我使用async / await来保持UI响应,以便它能够随时更新自己。 否则,在任何更新发生之前,必须完成长时间运行的任务。

由于长时间运行的任务在UI线程上(在您的示例中)已经同步,因此线程正在忙于执行您的方法,因此没有资源可用于刷新UI。执行该方法异步地在不同的线程上执行它,以便UI线程可以自由地执行UI相关操作,例如,渲染或更新绑定。

实施例

观点:

    <Window x:Class="TestRange.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:TestRange"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local:ViewModel x:Key="ViewModel" />
        </Window.Resources>
        <StackPanel DataContext="{StaticResource ViewModel}">
            <Button Content="Long Running Task" Command="{Binding LongRunningCommand}" />
            <TextBlock Text="{Binding Text}" />
        </StackPanel> 
</Window>

ViewModel:

class ViewModel : INotifyPropertyChanged
  {
    public ViewModel()
    {         
    }

    public ICommand LongRunningCommand => new RelayCommand(
      async (param) => await this.LongRunningTaskAsync().ConfigureAwait(false), (param) => true);

    public async Task LongRunningTaskAsync()
    {
      await Task.Run(
        () =>
        {
          for (int i = 0; i < 3; i++)
          {
            Thread.Sleep(5000);
            this.Text = $"Iteration #{i + 1}  completed";
          }
        });
    }

    private string text;   
    public string Text
    {
      get { return this.text; }
      set 
      { 
        this.text = value; 
        OnPropertyChanged();
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }

答案 1 :(得分:-1)

尝试以异步方式执行慢速方法(可能是阻塞方法),如下所示:

Log.addLine("Ledger initialized.");   
await Task.Run(() =>
{
    SlowMethod();
});
Log.addLine("slow1 operation.");