如何在显示进度条的同时异步地将用户控件加载到堆栈面板中
本文关键字:加载 控件 用户 堆栈 异步 显示 | 更新日期: 2023-09-27 18:24:40
我正在使用C#开发一个WPF应用程序。
我正试图了解异步线程和任务等。
基本上,我有一个用户控件,我把它添加到页面的堆栈面板中。可以将此用户控件的多次迭代添加到stackpanel中。
i.txtItemDescription.Text = "Item description " + ii.ToString() + ". Put a description here";
i.txtItemTitle.Text = "Item title " + ii.ToString() + ". Put a title here";
MainStack.Children.Add(i);
这很好用。然而,当我把这个应用程序转移到我的windows 8.1平板电脑上时,它会显著降低这些用户控件(UC)的显示速度。
我尝试过使用虚拟化,但没有效果,因为UC的数据访问和生成不会对性能产生影响。它是屏幕上控件的物理绘图。
所以我的问题如下:
- 在后台线程上运行此程序有助于提高性能吗
- 如果是这样的话,究竟是如何用BeginInvoke或Tasks加载堆栈面板的?我几乎尝试了这个网站上提到的每一个答案,要么我得到了STA错误,要么它根本没有达到我想要的效果
- 我对第2点的想法是,我想在表单上显示一个等待进度条(IsIndefinite=true),直到堆栈面板加载完成。但我完全被难住了。在所有情况下,表单UI都不会更新进度条,直到堆叠面板完全加载之后。在这种情况下已经太晚了
如有任何想法,我们将不胜感激!
Regds
Paul
首先,您不能在与最终呈现UI元素的线程不同的线程上创建UI元素,所以请忘记这种可能性。
如果是控件的物理绘制导致了性能问题,那么您可能没有正确使用UI虚拟化。UI虚拟化的全部目的是只对那些实际在视图中的控件执行布局和渲染,这意味着让某种项目(如ItemsControl
)根据需要生成相应的UI元素。预先填充整个面板会破坏目的,而且常规的StackPanel
无论如何都不支持虚拟化。我建议如下:
-
与其直接使用
StackPanel
,不如使用其ItemsPanelTemplate
中包含VirtualizingStackPanel
的ItemsControl
。 -
与其手动添加用户控件,不如将
ItemsSource
绑定到项目的底层列表,并让ItemsControl
在项目进入视图时为其生成容器。 -
使用
ItemTemplate
来定义项目的呈现方式,例如,模板内容应该是具有适当绑定的用户控件。
您可以在VirtualizingStackPanel
上尝试启用容器回收;根据您的使用情况,它可能有助于性能,也可能会影响性能。
无论如何,如果你遵循这个建议,你不应该需要进度指示器,因为你的项目的UI元素将在需要时生成,也就是说,当它们滚动到视图中时。
如果您以前从未将虚拟化与普通的旧ItemsControl
一起使用过(默认样式不支持它),那么您可以使用下面的样式作为起点。请注意,与默认的ItemsControl
样式不同,它支持滚动。
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility"
Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll"
Value="True" />
<Setter Property="ScrollViewer.PanningMode"
Value="Both" />
<Setter Property="Stylus.IsFlicksEnabled"
Value="False" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="VirtualizingStackPanel.IsVirtualizing"
Value="True" />
<Setter Property="VirtualizingStackPanel.VirtualizationMode"
Value="Recycling" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border x:Name="OuterBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Padding}"
Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter TargetName="OuterBorder"
Property="Background"
Value="{DynamicResource {x:Static apthemes:AssetResourceKeys.ListBackgroundDisabledBrushKey}}" />
</Trigger>
<Trigger Property="IsGrouping"
Value="True">
<Setter Property="ScrollViewer.CanContentScroll"
Value="False" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="VirtualizingStackPanel.IsVirtualizing"
Value="True">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>