Inserting Views into Regions in Prism V2 Alpha for Silverlight  

Wednesday, January 07 2009

Recently I was implementing a ReorderableListBox in Silverlight using Prism. Now the standard approach in Prism would be to write a ReorderableListBoxRegionAdapter and then register the type in your bootstrapper. After doing this and getting my reordering behavior working in a sample application without Prism, I ran into a brick wall around what I see as a glaring hole in Prism: IRegion does not allow Views to be inserted at an arbitrary position, they may only be added to the end of the list.

Clearly without the ability to insert dynamically my reordering behavior was up the river without a paddle. Now after digging through the Prism source code I have a very clean, workable solution that I would like to eventually get into Prism itself.

If you do not want to see the details of how I did this, you can download it here and stop reading now. For those foolish souls who want to listen to my banter, read on. The problem revolves around the fact that although ViewsCollection implements INotifyPropertyChanged it does not implement IList. The ViewsCollection class is responsible for filtering the underlying collection of ItemMetadata and keeping these collections up to date. It updates these filters by responding to CollectionChanged events in the underlying collection. It’s response to NotifyCollectionChanged.Add is:


case NotifyCollectionChangedAction.Add:
  foreach (ItemMetadata itemMetadata in e.NewItems)
  {
    itemMetadata.MetadataChanged += itemMetadata_MetadataChanged;
    if (filter(itemMetadata))
    {
      changedItems.Add(itemMetadata.Item);
    }
  }
  AddAndNotify(changedItems);
  break;

This is where the fundamental problem arises. You see, when you perform an Insert in WPF or Silverlight, a NotifyCollectionChangedArgs is created with StartingItemIndex set to the index in the list that you wish to insert at. As you can see, the above code completely ignores this information and simply performs a simple add. To rectify this issue, I simply made the StartingItemIndex meaningful, and implemented IRegion.Insert across the library:


case NotifyCollectionChangedAction.Add:
  int startIndex = e.NewStartingIndex;

  foreach (ItemMetadata itemMetadata in e.NewItems)
  {
    itemMetadata.MetadataChanged += ItemMetadataMetadataChanged;
    if (filter(itemMetadata))
    {
      InsertAndNotify(itemMetadata.Item, startIndex);
      startIndex++;
    }
  }
  break;

Some additional changes were necessary to InsertAndNotify, but these changes are merely a consequence of this fundamental change in how the CollectionChanged event is handled. You can download the source here. The README includes instructions on how to integrate it into your existing CAL project. I’ll let you know if this makes it into the Prism source!


  • Posted by Charlie Robbins

Post a comment


(required, but not displayed)

(optional)