问题是:我可以拆分我的 DataGrid 或 ItemsControl 以在更小的块中呈现控件,以便 UI 不会被阻塞 15 秒来呈现整个控件吗?
我实际上认为渲染不会阻塞 UI,因为它是在不同的线程中制作的。
我的 ItemsControl 托管了几个(最多 20 个)数据网格。其中一些可以包含多达 100 行,而一些只有 1 行短。当我填充项目的底层 ObservableCollection 时,我遇到了严重的滞后。
这是我要做什么的简要说明:
- 在 UIThread 我选择了一些数据。
- 此数据将发送到 VM 2.5。VM 设置 IsBusy 标志,使 ItemsControl 将模板更改为加载占位符屏幕。
- VM 在 BackgroundWorker 中发出多个数据库请求
- VM BackgroundWorker Dispatcher.Invokes DataViews 返回到 VM 的 ObservableCollection 一次一个 DataView 到目前为止一切正常:UI 负责,进度条更新等等,但是:
- VM 信号:IsBusy=false => ItemsControl 将其模板更改回其原始状态
- UI挂起约 15 秒以呈现 ItemsControl 中的所有 DataGrid(我可以看到 CPU 高 CPU 使用率)
这是一些代码:
XAML(我将 ItemsControl 放在 ScrollViewer 中,因为我发现这是使内容可滚动的唯一方法。):
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="1" Grid.Row="0"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsControl
DataContext="{Binding Source={StaticResource TerminalMaskVM}}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
Style="{StaticResource LoadingControl}"
ItemsSource="{Binding Source={StaticResource TerminalMaskVM}, Path=TerminalMasks}"
x:Name="MaskContainer">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander IsExpanded="True" Header="{Binding MaskTableName}">
<gui:DataGrid ItemsSource="{Binding MaskTable}"
EnableColumnVirtualization="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
...columns definitions, etc..
...closing tags here
我对这个问题进行了广泛的搜索,并尝试了以下方法:
- 指定 VirtualizingStackPanel.IsVirtualizing="True" 和 VirtualizingStackPanel.VirtualizationMode="Recycling"
- 试图将 ItemsControl 容器切换到 DockPanel
- 将 RowHeight 和 columns Width 设置为固定值
所有这些都不会影响渲染时间。