question

RichardHaggard-0887 avatar image
0 Votes"
RichardHaggard-0887 asked PeterFleischer-3316 edited

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

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-wpf
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered PeterFleischer-3316 edited

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>
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.