I've always had long loading times with WPF DataGrids, and I cannot find any similar reports online, so I suspected that I was doing something wrong. Now I am sure of it, since adding layout complexity considerably slows down execution. In a very simple layout, the DataGrid populates instantaenously, whereas the code below takes around 3 seconds to execute.
In the following code, it takes ~3 seconds for 150 rows and 11 columns to load, even if each cell is not bound to any property and with AutoGenerateColumns=False. (I have a two core, 2.6GHz processor with plenty of RAM).
The bottle neck takes place when the ItemsSource property is set in a layout as the one below:
<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;
}
}
}
The problem only occurs when the DataGrid is embedded inside a ScrollViewer like:
<ScrollViewer>
<Datagrid/>
</ScrollViewer>
This makes sense because this configuration causes the whole DataGrid to be drawn at the same time (to be able to size the ScrollViewer's client area correctly). In essence, it overrides the built-in virtualization behavior of the DataGrid, which implements its own ScrollBars so that not all of its content has to be placed in the layout simultaneously.
In other words, embedding a DataGrid inside a ScrollViewer is rarely needed because the DataGrid has its own automatic scrolling.