On-the-fly updating of a data template selected by a DataTemplateSelector

1 minute read

It’s really fun when someone contacts you with a Windows Phone development problem and you have already something standing by to solve it – even if it was intended for something completely different. Last week fellow MVP Mark Monster contacted me with the following situation:

  • He had several objects in an ObservableCollection
  • He was using a DataTemplateSelector to determine which template was to be used for an object – I assume he used something like this.

This worked very fine when initially binding the list of objects to the LongListSelector, but he ran into the following problem: the template to be used was determined by an attribute that could be changed while the object was visible. Like, in the example by the article on geekchamp.com that I referred to, you could change the Food Type from healthy to unhealthy after the list was displayed. But if Mark did that, the template stayed the same. The new template was not selected.

This is of course perfectly understandable – the template selector, being a ContentControl, just has as OnContentChanged you can override - but has no knowledge about what is going on in the collection from which its instances are created.

The solution is very simple, albeit a bit crude – reaching back into the last post of my 4-part mapping series, I pulled out this brilliant *cough* piece of coding, originally cobbled together to compensate for a bug I in my own CodePlex library:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace Wp7nl.Utilities
{
  public class ResettableObservableCollection<T> : ObservableCollection<T>
  {
    public ResettableObservableCollection()
    {
    }

    public ResettableObservableCollection(List<T> list)
      : base(list)
    {
    }

    public ResettableObservableCollection(IEnumerable<T> list)
      : base(list)
    {
    }

    public void ForceReset()
    {
      OnCollectionChanged(
       new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
  }
}

The only thing Mark needed to do was:

  • Change his standard ObservableCollection into a ResettableObservableCollection,
  • Call “ForceReset” on the collection after he had changed the attribute that should trigger the template change.

This will work on Windows Phone 8 as well on Windows Phone 7. It’s crude, but effective. Sometimes life is so simple - so simple in fact that that I hope you will forgive me for omitting a demo solution this time. I hope this helps more people wrestling with the same problem.

Which reminds me I should update my wp7nl library on CodePlex again. The additions are backing up again ;-)