c# - WPF UI 线程被大集合阻塞

标签 c# wpf xaml mvvm

我有一个使用 MVVM 构建的 WPF 应用程序;其中一个 View 包含一组长度在 200-500 之间的模型,每个模型都映射到 RepositoryViewModel 并绑定(bind)到堆栈面板中的“Repository.xaml” View 。

顶层 View (Main.xaml)如下:

<Window.Resources>
    <DataTemplate DataType="{x:Type home:RepositoryViewModel}">
        <vw:Repository />
    </DataTemplate>
<Window.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Margin="5 40 5 5">
    <StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
        <ItemsControl ItemsSource="{Binding Repositories}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>

Repository.xaml UserControl如下:

<Grid Margin="5" Visibility="{Binding Model.Visibility}" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition SharedSizeGroup="WrapPanelGroup" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>

    <StackPanel Grid.Column="1">     
        <!--Textbox is used to allow user to select the text. Changing to Label does not help with rendering issues-->       
        <TextBox Background="Transparent" BorderThickness="0" Text="{Binding Model.Name}" IsReadOnly="True"
                 TextWrapping="Wrap" FontSize="18" MaxWidth="300" />
        <TextBox Background="Transparent" BorderThickness="0" Text="{Binding Model.Url}" IsReadOnly="True"
                 TextWrapping="Wrap" FontSize="8" MaxWidth="300" Foreground="DarkGray" />
    </StackPanel>
    <Button Grid.Column="2" Content="Checkout" Command="{Binding CheckoutCommand}" Visibility="{Binding Model.SingleCheckoutVisible}"/>
    <CheckBox Grid.Column="2" IsChecked="{Binding Model.IsChecked}" Visibility="{Binding Model.BulkCheckoutVisible}"/>
</Grid>

以上内容完全符合我的要求,问题是 WPF 渲染控件所花费的时间 - 一旦将每个 RepositoryViewModel 添加到 RepositoryViewModel ObservableCollection 整个 UI 在呈现控件时卡住 3-5 秒。

在尝试隔离问题时,我注意到通过删除文本框的渲染时间会显着减少,但删除文本框上的绑定(bind)不会产生明显的差异。将文本框换成标签几乎没有什么区别。

集合大小是否只是为了让 WPF 能够快速处理而过大,还是我遗漏了一些会增加渲染时间的东西?我确实考虑过具有 MaxWidth 的 SharedSizeGroup 可能是罪魁祸首,但删除并没有提高性能。

谢谢。

最佳答案

考虑将虚拟化添加到您的 ItemsControl。这样它只会呈现 View 中的项目而不是所有项目。

<ItemsControl VirtualizingStackPanel.IsVirtualizing="True"
              ScrollViewer.CanContentScroll="True">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

我相信您还需要从 StackPanel 和 ScrollViewer 中删除 ItemsControl,因为它们会为 ItemsControl 提供无限的渲染空间,并使虚拟化变得无用。

我看到您正在为 ItemsPanelTemplate 使用 WrapPanel,因此您可能需要推出自己的虚拟化面板,或者查看一些 other controls (我自己没用过)。

关于c# - WPF UI 线程被大集合阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33548213/

相关文章:

c# - 从另一个线程返回对象?

c# - MVVM 的上下文相关命令

c# - 在没有 MVVM 框架的情况下创建子窗口

c# - 通过 XAML 实例化 View 时 SimpleInjector.Container.Verify 中出现 NullReferenceException

c# - 锁定每个用户的创建/更新/删除请求

wpf - 如何根据一列中的值更改 DataGrid 行的背景

c# - 使用依赖属性设置标签内容

xaml - "Shortcut"用于设置ListViewItem选定背景

c# - 使用 Linq 重新排列表数据

c# - 自定义工具错误 : after switching project from .net 4.5 到 .Net 4.6.1