1

I have an ObservableCollection bound to a WPF DataGrid. The ObservableCollection is populated and updated asynchronously.

The DataGrid is not displaying the correct number of rows. Each time I run the application I get a varying number rows displayed, usually 7-8 but sometimes only one. I get the same behvaior with ListBox, but not with ComboBox.

I get this same behavior with a ListBox and ItemsControl but not with ComboBox. The ComboBox correctly displays all 18 items as expected.

EDIT

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

I'll need to do some more detective work here as my presumption was the updates were happening in the same thread. So the reason for the first few items being displayed correctly is that the ViewModel was able to retrieve some of the data before the View itself loaded.

Brian
  • 6,910
  • 8
  • 44
  • 82

2 Answers2

1

I can confirm that this is indeed a threading issue. I am an idiot for dumping the exceptions when adding to the collection, because I probably would have spotted the error sooner! Never do this! It is bad pratice.

Possible solutions to this problem are addressed here:

ObservableCollection and threading

Community
  • 1
  • 1
Brian
  • 6,910
  • 8
  • 44
  • 82
0

Use this code:
(Notice that DownloadedItem and it´s properties must also be using INotifyPropertyChanged as in this example)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    class Downloads : NotifyBase
    {
        public virtual ObservableCollection<DownloadedItem> DownloadedItemCollection
        {
            get { return _DownloadedItemCollection; }
            set { _DownloadedItemCollection = value; OnPropertyChanged(System.Reflection.MethodBase.GetCurrentMethod().Name.Substring(4));  /*OnPropertyChanged("DownloadedItemCollection");*/ }
        } private ObservableCollection<DownloadedItem> _DownloadedItemCollection;

    }
}

public class NotifyBase : INotifyPropertyChanged
{
    #region NotifyBase
    // Declare the event
    public virtual event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}
Tony
  • 16,527
  • 15
  • 80
  • 134
  • This is very similar to what I have in place only I have the string for the property name hard coded instead of using reflection. I am correctly getting all of the notifications as expected in my ViewModel so I don't think it's a problem at this level. The list is bound to the colletion, so it seems like the problem lies between the ObservableColletion and list or grid. – Brian Feb 12 '11 at 16:55