如何在WPF中长时间运行UI进程之前(和之后)更新UI?

时间:2013-09-10 13:35:12

标签: c# wpf user-interface dispatcher

如果这是重复的话,我道歉,但我无法找到类似情况的问题。如果这是重复,请提供链接。

我想在我的WPF应用程序中显示“正在加载...”覆盖,当我动态创建大量标签时。叠加可见性绑定到名为“ShowIsLoadingOverlay”的属性。但是,从不显示叠加层。

由于选项卡是可视元素,我无法将创建移动到BackgroundWorker中。

我已经创建了一个小型原型试图解释这种情况。这是xaml:

<Window x:Class="WpfApplication5.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Label HorizontalAlignment="Center" VerticalAlignment="Center" 
               Visibility="{Binding ShowIsLoadingOverlay, Converter={StaticResource BooleanToVisibilityConverter}}" 
               Content="Loading..." />

        <Button Grid.Row="1" Content="Load" Click="Button_Click" />
    </Grid>
</Window>

这就是背后的代码:

public partial class MainWindow : Window, INotifyPropertyChanged
{
   private bool m_ShowIsLoadingOverlay;
   public bool ShowIsLoadingOverlay
   {
      get
      {
         return m_ShowIsLoadingOverlay;
      }
      set
      {
         if ( m_ShowIsLoadingOverlay == value )
         {
            return;
         }

         m_ShowIsLoadingOverlay = value;
         NotifyPropertyChanged( "ShowIsLoadingOverlay" );
      }
   }

   public MainWindow()
   {
      InitializeComponent();

      DataContext = this;
   }

   private void Button_Click( object sender, RoutedEventArgs e )
   {
      ShowIsLoadingOverlay = true;

      CreateTabs();

      ShowIsLoadingOverlay = false;
   }

   private void CreateTabs()
   {
      // Simulate long running process to create tabs
      Thread.Sleep( 3000 );
   }

   // Implementation of INotifyPropertyChanged has been left out.
}

问题是从不显示叠加层。我知道它与在ShowIsLoadingOverlay属性发生变化之前和之后未正确更新的UI有关。而且我认为这也与缺乏使用调度员有关。

在更改属性和/或围绕CreateTabs调用时,我尝试了很多很多Dispatcher.Invoke,Dispatcher.BeginInvoke的组合。我已经尝试在开始创建选项卡之前更改DispatcherPriority以“强制”显示叠加层。但我无法让它发挥作用......

你能告诉我如何完成这项任务吗?更重要的是;提供解释,因为我没有得到这个。

事先, 谢谢。

祝你好运, CasperKorshøj

1 个答案:

答案 0 :(得分:0)

您无法在后台线程中操纵UI控件。如果您使用主UI线程来创建TabItem,那么您也无法拥有一个忙碌的&#39;或者&#39;正在加载&#39;指示符...如果您在长时间运行的过程中使用备用线程,这将工作。这是因为你的忙碌&#39;只有在长时间运行的进程在同一个UI线程上运行时,指示符才会更新。