10

我一直有很长的 WPF DataGrids 加载时间,我在网上找不到任何类似的报告,所以我怀疑我做错了什么。现在我确定了,因为增加布局复杂性会大大减慢执行速度。在一个非常简单的布局中,DataGrid 会立即填充,而下面的代码大约需要 3 秒才能执行。

在以下代码中,加载 150 行和 11 列需要大约 3 秒,即使每个单元格未绑定到任何属性且 AutoGenerateColumns=False。(我有一个带有大量 RAM 的两核 2.6GHz 处理器)。

当 ItemsSource 属性在如下布局中设置时,就会出现瓶颈:

<Window x:Class="datagridtest.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">
<Border  Background="LightSteelBlue" CornerRadius="10" Margin="10">
    <ScrollViewer Margin="10" HorizontalScrollBarVisibility="Auto">
        <Grid Margin="10,50,0,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"  />
                <RowDefinition Height="auto" />
                <RowDefinition Height="auto" />

            </Grid.RowDefinitions>
            <Expander IsExpanded="True" Name="expander1"  Grid.Row="0">
                <Grid>
                    <DataGrid VirtualizingStackPanel.IsVirtualizing="True" AutoGenerateColumns="false" Name="dg" Height="auto" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False">
                        <DataGrid.Columns>
                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>



                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>


                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>

                            <DataGridTextColumn >
                                <DataGridTextColumn.Header >
                                    <TextBlock Width="140" HorizontalAlignment="Center" TextAlignment="Center">untitled<LineBreak/>column</TextBlock>
                                </DataGridTextColumn.Header>
                            </DataGridTextColumn>



                        </DataGrid.Columns>
                        </DataGrid>
                </Grid>
            </Expander>

            <Expander IsExpanded="true"  Grid.Row="1">
                <Grid>
                    <DataGrid AutoGenerateColumns="True"  Height="auto" />
                </Grid>
            </Expander>

            <Expander IsExpanded="true"    Grid.Row="2">
                <Grid>
                    <DataGrid AutoGenerateColumns="True" Height="auto" />
                </Grid>
            </Expander>
            <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="121,-42,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click_2" />
        </Grid>
    </ScrollViewer>
</Border>

using System.Collections.ObjectModel;

namespace datagridtest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();


    }

    class row
    {
        public string Name { get; set; }
        public double Age { get; set; }
    }



    private void button1_Click_2(object sender, RoutedEventArgs e)
    {
        ObservableCollection<row> src = new ObservableCollection<row>();

        for (int i = 0; i < 150; i++)
            src.Add(new row { Name = i.ToString(), Age = i / 2 });

        dg.ItemsSource = src;
    }
}
}
4

4 回答 4

17

仅当 DataGrid 嵌入到 ScrollViewer 中时才会出现此问题,例如:

<ScrollViewer>
    <Datagrid/>
</ScrollViewer>

这是有道理的,因为此配置会导致同时绘制整个 DataGrid(以便能够正确调整 ScrollViewer 的客户区的大小)。本质上,它覆盖了 DataGrid 的内置虚拟化行为,后者实现了自己的 ScrollBars,因此不必同时将其所有内容放在布局中。

换句话说,很少需要在 ScrollViewer 中嵌入 DataGrid,因为 DataGrid 有自己的自动滚动功能。

于 2010-07-26T18:27:04.847 回答
7

我在包含 DataGrid 的 UserControl 上遇到了类似的问题,有时当我将 UserControl 放在新表单或另一个 UserControl 上时,它会在重新绘制 DataGrid 时锁定界面(5 秒?)。与调整大小相同。

我追踪到

行定义高度=“自动”

如果我将 UserControl 放在 StackPanel 中,也会发生同样的性能问题。当需要填充整个数据网格以计算封装容器的大小时,似乎与前面提到的调整大小错误有很大关系。

<UserControl x:Class="ExampleUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" d:DesignHeight="481" d:DesignWidth="773">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" /> <!-- 'AUTO' CAUSES EXTREMELY POOR PERFORMANCE -->
        </Grid.RowDefinitions>

        <Grid Grid.Row="0"> <!-- CHANGING TO STACKPANEL CAUSES EXTREMELY POOR PERFORMANCE -->
            <ContentControl Content="{Binding MyDataGridUserControl}" />
        </Grid>
    </Grid>

</UserControl>

根据之前的评论,我刚刚发现为 ContentControl 设置 MaxHeight="[whatever]" 也有效。它可以比屏幕大。

于 2011-09-14T03:33:24.130 回答
3

你能看到是否所有的行都是按布局生成的吗?通常虚拟化应该会阻碍这一点并且只生成可见的行。(使用其中一列中的模板对其进行测试,并在构造函数中对其进行计数)。如果 WPF 在尝试调整为最大列时无法确定 DataGrid 的正确宽度,则会出现错误 - 因此必须生成所有行来计算具有最大宽度的行。(要测试最后一个 - 将其放在停靠面板而不是网格中 - 停靠在左侧或右侧)

另外,尝试 VirtualizingStackPanel.VirtualizationMode="Recycling" 让它回收使用的模板。

于 2010-07-26T18:02:02.940 回答
0

我对绑定数据网格有同样的问题,我注意到在第一次加载时它很快,但在第二次和下一次加载时很慢。所以当我添加代码时:

DataGrid.ItemsSource = Nothing

进而

TableAdapter.Fill(Mydataset.MyStoredProcedure,....)
DataGrid.ItemsSource=Mydataset.MyStoredProcedure

它变得非常快。

于 2015-04-16T11:10:11.427 回答