How to speed up a WPF DataGrid bound to an ObservableCollection?

Richard Haggard 6 Reputation points
2020-06-17T15:26:34.737+00:00

The application is WPF/MVVM. A DataGrid's ItemSource is bound to an ObservableCollection<LogItem> where LogItem is a plain class of 5 strings and one enumerated value, none of which support the INotifyPropertyChanged interface. The problem is that the time between when the ObservableCollection is updated and when the DataGrid actually displays anything seems excessively long and I'm hoping there's some way to speed this up.

Here's what I mean. There is a button whose command causes a UserControl to get created. In the UC's associated ViewModel class constructor the ObservableCollection is populated with about 1600 items. The actual population is quick but the UI thread stalls for about 15 seconds which is unexpectedly long. What I suspect is happening is that the DataGrid itself is handling a boat load of notifications from the ObservableCollection and due to sorting and what not it just takes a while.

On the other hand, I've been using DataGrids for years and haven't ever seen anything this poor in performance before but normally I use a DataTable instead of an ObservableCollection.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,706 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,311 Reputation points
    2020-06-18T06:01:23.957+00:00

    Hi, without knowing your code, it is impossible to investigate your problem. The following small demo shows that the 1600 data rows with 6 columns are displayed very quickly. They are not loaded in the constructor, but only when the DataGrid in the UserControl only fetches the data for display.

    <Window x:Class="Window032"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1.WpfApp032"
            xmlns:uc="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
            mc:Ignorable="d"
            Title="Window032" Height="450" Width="800">
      <Window.DataContext>
        <local:ViewModel/>
      </Window.DataContext>
      <Grid>
        <uc:Window032UC1/>
      </Grid>
    </Window>
    

    Imports System.Collections.ObjectModel
    Imports System.ComponentModel
    
    Namespace WpfApp032
      Public Class ViewModel
        Public ReadOnly Property View As ICollectionView
          Get
            If cvs.Source Is Nothing Then
              getData()
              cvs.Source = col
            End If
            Return cvs.View
          End Get
        End Property
    
        Private cvs As New CollectionViewSource
        Private col As ObservableCollection(Of LogItem)
    
        Private Sub getData()
          col = New ObservableCollection(Of LogItem)
          For i = 1 To 1600
            col.Add(New LogItem With {.ID = i, .String1 = $"String1: {i}", .String2 = $"String2: {i}", .String3 = $"String3: {i}", .String4 = $"String4: {i}", .String5 = $"String5: {i}"})
          Next
        End Sub
      End Class
    
      Public Class LogItem
        Public Property ID As Integer
        Public Property String1 As String
        Public Property String2 As String
        Public Property String3 As String
        Public Property String4 As String
        Public Property String5 As String
      End Class
    
    End Namespace
    

    <UserControl x:Class="Window032UC1"
                 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" 
                 xmlns:local="clr-namespace:WpfControlLibrary1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <Grid>
        <DataGrid ItemsSource="{Binding View}"/>
      </Grid>
    </UserControl>
    
    0 comments No comments