DataGrid Does Not Update When Items Added to ObservableCollection in Silverlight


I have a Silverlight application which interacts with a WCF service. It periodically receives new items to add to a list from this service, and each new element is added to the end of an ObservableCollection (collection.Add() for each new element).

The items themselves don't change once they are received, and the items' class inherits INotifyPropertyChanged, however when I add new items (received from WCF), the DataGrid doesn't update.
I am also using a custom formatter for the DataGrid binding, but I don't think this is a problem as the initial set of items appear correctly (when the ItemsSource is first set).

I would have expected the new elements to appear, as I have confirmed that the ObservableCollection is emitting the correct add event. Since ObservableCollection inherits from INotifyCollectionChanged, shouldn't it update the DataGrid?

The only solution I have found so far is:

dataGrid.ItemsSource = null;
dataGrid.ItemsSource = collection;

Any ideas on how to get it updating? This method blocks the UI for a noticable amount of time.


The elements are expanded and extracted in the WCF callback event:

// The ItemWrapper allows the Binding converter to be passed the entire trade object, rather than just each property.
ObservableCollection<ItemWrapper<ExpandedTrade>> pastTrades = new ObservableCollection<ItemWrapper<ExpandedTrade>>();

       // Extract and expand data - MinimalTrade is the data sent through WCF
       var convertedTrades = from MinimalTrade t in e.trades
                                  select new ItemWrapper<ExpandedTrade>(
                                      new ExpandedTrade(t,
                                          usernames.ContainsKey(t.UserToId) ? usernames[t.UserToId] : null, potentialWealth != null ? potentialWealth.CurrentWealth : null)); // Get name, otherwise null.
       // Data now expanded (to show full information like usernames
       // pastTrades is an observableCollection
            foreach (var trade in convertedTrades)

The OnNewMyTradeHistory event then does this:

if (tradeHistory.ItemsSource == null) tradeHistory.ItemsSource = trades;

This only sets ItemsSource once (to the ObservableCollection) and the add events are firing, but nothing is happening on the UI side.

The WCF callbacks might be happening in another thread.

I found the solution!

I had implemented the Equals, GetHashCode and ToString methods in both ItemWrapper and ExpandedTrade:

ItemWrapper.cs: (Calls the equivalent methods in the child class)

    public override bool Equals(object obj)
        if(obj is T) return Quote.Equals(obj);
        if (obj is ItemWrapper<T>) return Quote.Equals(((ItemWrapper<T>)obj).Quote);
        return this == obj;
    public override int GetHashCode() { return Quote.GetHashCode(); }
    public override string ToString() { return Quote.ToString(); }


    public override bool Equals(object obj)
        if (obj == null) return false;
        ExpandedQuote q = obj as ExpandedQuote;
        if (q == null) return false;
        return q.Id == Id;

    public override int GetHashCode() { return Id; }

After removing these methods, it worked. I'd imagine that the DataGrid was testing for equality somewhere, and somehow something was returning an incorrect test. The IDs are unique, but by using the default test of equality by reference, it now works.