Reputation: 4096
In my .NET 3.5
WPF
Application, I have a WPF
DataGrid
which will be populated with 500 columns and 50 rows.
The performance of App is very very poor in scrolling, or when I do DataGrid.Items.Refresh()
or in selecting rows.
Actually App will take around 20 sec to Update Layout. Layout_Updated()
event will trigger after 20 sec.
If I reduce the columns to 50 or less, App will be very responsive. As per my findings performance is directly related to column count.
How do I improve the DataGrid
performance?
Upvotes: 42
Views: 51455
Reputation: 2878
I was having a DataGrid in a ScrollViewer allowing for the DataGrid
to grow to infinite height. Setting the Height
or the MaxHeight
of the DataGrid to something reasonable was solving the majority of my performance problems.
Upvotes: 1
Reputation: 626
One soltuion that I found to be the best compromise for both loading and scrolling performance is to set the IsAsync=True
for all the columns' Binding not the DataGrid ItemsSource Binding. Example:
<DataGridTextColumn Binding="{Binding Path=MaterialName, Mode=OneTime, IsAsync=True}" Header="Name" />
By the way, this solution works better when virtualization on the DataGrid is switched off. However, even if virtualization is switched on, still worth a try. Also this solution is very effective when applied to a DataGridTemplateColumn that displays an image or so.
Upvotes: 0
Reputation: 2803
This answer (Set ScrollViewer.CanContentScroll to True) put me on the right track. But I need it to be set to false
. To set it to true
when I'm doing my refresh I wrote this two methods.
internal static void DataGridRefreshItems(DataGrid dataGridToRefresh)
{
/// Get the scrollViewer from the datagrid
ScrollViewer scrollViewer = WpfToolsGeneral.FindVisualChildren<ScrollViewer>(dataGridToRefresh).ElementAt(0);
bool savedContentScrollState = scrollViewer.CanContentScroll;
scrollViewer.CanContentScroll = true;
dataGridToRefresh.Items.Refresh();
/// Was set to false, restore it
if (!savedContentScrollState)
{
/// This method finishes even when the update of the DataGrid is not
/// finished. Therefore we use this call to perform the restore of
/// the setting after the UI work has finished.
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => SetScrollViewerCanContentScrollFalse(scrollViewer)), DispatcherPriority.ContextIdle, null);
}
}
private static void SetScrollViewerCanContentScrollFalse(ScrollViewer scrollViewer)
{
scrollViewer.CanContentScroll = false;
}
This is the method I use to get the VisualChildren:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
After this my refresh of 50.000 new items lasts only 10 seconds unlike 2 Minutes and consumes only 2 MB of RAM instad of 4 GB before.
For testing I disabled all of my IValueConverter
and implemented properties which I bind directly. Without the converters the DataGrid refreshes immediately. So I left it.
Upvotes: 1
Reputation: 4360
Set the DataGrid.RowHeight
value and that will make a huge difference.
I know this is a really old question, but I just came across it, and this was the biggest difference on my end. My default height was 25.
Upvotes: 4
Reputation: 131
Check if you have property ScrollViewer.CanContentScroll
set False
.
Setting this property to false disables the virtualization in a way will degrade the performance of your Data-grid. For more clarification refer this CanContentScroll
Upvotes: 13
Reputation: 7951
There are a few options you can turn on to help you on your DataGrid object
EnableColumnVirtualization = true
EnableRowVirtualization = true
These two are the main ones I think might help. Next try making your binding async
ItemsSource="{Binding MyStuff, IsAsync=True}"
And lastly, I've heard that setting a maximum height and width can help even if it above the max screen size, but I didn't notice a difference myself (claim had to do with auto size measuring)
MaxWidth="2560"
MaxHeight="1600"
Also never put a DataGrid
in a ScrollViewer
, because you will essentially lose virtualization. Let me know if this helps!
Upvotes: 96
Reputation: 399
Maybe try this instead of loading all 50 rows at once
http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization
Upvotes: 0