Неоправданное время загрузки WPF DataGrid - PullRequest
9 голосов
/ 26 июля 2010

У меня всегда было много времени загрузки с WPF DataGrids, и я не могу найти подобные отчеты в Интернете, поэтому я подозревал, что что-то делал не так.Теперь я в этом уверен, так как добавление сложности макета значительно замедляет выполнение.В очень простом макете DataGrid заполняется мгновенно, тогда как выполнение приведенного ниже кода занимает около 3 секунд.

В следующем коде загрузка ~ 150 строк и 11 столбцов занимает ~ 3 секунды, даже если каждыйячейка не привязана ни к какому свойству и имеет AutoGenerateColumns = False.(У меня есть двухъядерный процессор с тактовой частотой 2,6 ГГц и большим количеством оперативной памяти).

Сужение бутылок происходит, когда свойство 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 ]

17 голосов
/ 26 июля 2010

Проблема возникает, только когда DataGrid встроен в ScrollViewer, например:

<ScrollViewer>
    <Datagrid/>
</ScrollViewer>

Это имеет смысл, потому что эта конфигурация приводит к тому, что вся DataGrid рисуется одновременно (чтобы можно было измерить размерКлиентская область ScrollViewer правильно).По сути, он переопределяет встроенное поведение виртуализации в DataGrid, который реализует собственные ScrollBars, так что не все его содержимое должно быть одновременно размещено в макете.

Другими словами, встраивание DataGrid внутриScrollViewer редко требуется, потому что DataGrid имеет собственную автоматическую прокрутку.

5 голосов
/ 14 сентября 2011

У меня была похожая проблема с UserControl, который содержал DataGrid, иногда, когда я помещал UserControl в новую форму или другой UserControl, он блокировал интерфейс (5 секунд?), Пока он перерисовывал DataGrid. То же самое с изменением размера.

Я отследил его до

RowDefinition Height = "Авто"

и та же проблема с производительностью также возникала, если я помещал 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>

Я только что обнаружил, что установка MaxHeight = "[what]" для ContentControl также работает, как в предыдущем комментарии. Может быть больше экрана.

3 голосов
/ 26 июля 2010

Можете ли вы увидеть, все ли строки генерируются по макету?Обычно виртуализация должна препятствовать этому и генерировать только видимые строки.(Протестируйте его с помощью шаблона в одном из столбцов и сосчитайте в конструкторе).Существует ошибка, если WPF не может определить правильную ширину DataGrid, поскольку он пытается определить размер до наибольшего столбца - таким образом, необходимо сгенерировать все строки, чтобы вычислить ту, которая имеет наибольшую ширину.(Чтобы проверить последний - поместите его на панель док-станции вместо сетки - закрепите влево или вправо)

Кроме того, попробуйте VirtualizingStackPanel.VirtualizationMode = "Recycling", чтобы позволить ему перерабатывать используемые шаблоны.

0 голосов
/ 16 апреля 2015

У меня та же проблема с привязанной сеткой данных, и я замечаю, что при первой загрузке это происходит быстро, а при второй и следующей - медленно.Поэтому, когда я добавляю код:

DataGrid.ItemsSource = Nothing

, а затем

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

он становится очень БЫСТРОМ.

...