【问题标题】:How to update UI before (and after) long running UI process in WPF?如何在 WPF 中长时间运行的 UI 进程之前(和之后)更新 UI?
【发布时间】:2013-09-14 06:03:36
【问题描述】:

如果这是重复的,我深表歉意,但我无法找到类似情况的问题。如果这是重复的,请提供一个链接。

当我动态创建大量选项卡时,我想在我的 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 更改为“强制”显示覆盖。但我就是不能让它工作......

您能告诉我如何完成这项任务吗?更重要的是;提供解释,因为我不明白。

提前, 谢谢。

最好的问候, 卡斯珀·科尔什霍伊

【问题讨论】:

  • CreateTabs 是做什么的?您不应在 WPF 中的代码中创建或操作 UI 元素。此外,该代码可能不属于后面的代码。
  • @I4V:但是否可以使用 async 和 await 创建 UI 元素(属于 UI 线程)?
  • @HighCore:CreateTabs 是一种根据一些用户角色动态生成一些选项卡的方法。在 WPF 的代码中创建和操作 UI 元素有什么问题?

标签: c# wpf user-interface dispatcher


【解决方案1】:

您不能在后台线程中操作 UI 控件。如果您使用主 UI 线程来创建您的 TabItems,那么您也不能有“忙碌”或“正在加载”指示器...在您使用替代方法时才有效为您的长时间运行的进程提供线程。这是因为如果长时间运行的进程在同一个 UI 线程上运行,那么只有在长时间运行的进程完成后,您的“忙碌”指示器才会更新。

【讨论】:

  • 但是在进入长时间运行的进程之前,有没有办法“释放”主 UI 线程?或者在加载指示器显示后使用某种回调来推迟 CreateTabs 调用?
猜你喜欢
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 2013-03-19
相关资源
最近更新 更多