Development Tip - ObservableCollection doesn't work

NOTE: This post applied in an the early preview of Win8. It's no longer applicable because the bug in question no longer exists; ObservableCollection works just great :)

Original article below.

 

 

Just getting started with Win8 development, and will note what I learn in a series of posts.

 

I'm finding that ObservableCollection isn't being honored by XAML elements in the //BUILD version of the tools. More specifically, either it's not firing collection changed events, or it is but they're being ignored. Seems this is a known limitation of the current dev drop, and there's an ObservableVector<object> which does work. However, using that throughout your code hurts because of all the casting required; it will also be messy to change when the tools catch up.

Until then, I created this wrapper that derives from ObservableCollection<T>, but also implements IObservableVector<object>. When the tools are fixed, you should be able to do a simple search/replace with ObservableCollection.

Please note that this isn't tested, it's not serious work, it's 5 minutes of Band-Aid which "seems to work on my machine". Use at own risk, etc.

 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using Windows.Foundation.Collections;
  
 namespace W8Shared
 {
     public class BindableObservableCollection<T> : ObservableCollection<T>, IObservableVector<object>
     {
         public event VectorChangedEventHandler<object> VectorChanged;
  
         public int IndexOf(object item)
         {
             return base.IndexOf((T)item);
         }
  
         public void Insert(int index, object item)
         {
             base.Insert(index, (T)item);
             RaiseChange(CollectionChange.ItemInserted, (uint)index);
         }
  
         private void RaiseChange(CollectionChange type, uint index)
         {
             if (VectorChanged != null)
                 VectorChanged(this, new VectorChangedEventArgs(type, index));
         }
  
         public new object this[int index]
         {
             get
             {
                 return (object)base[index];
             }
             set
             {
                 base[index] = (T)value;
                 RaiseChange(CollectionChange.ItemChanged, (uint)index);
             }
         }
  
         public void Add(object item)
         {
             base.Add((T)item);
             RaiseChange(CollectionChange.ItemInserted, (uint)(base.Count-1));
         }
  
         public bool Contains(object item)
         {
             return base.Contains((T)item);
         }
  
         public void CopyTo(object[] array, int arrayIndex)
         {
             throw new NotImplementedException();
         }
  
         public bool IsReadOnly
         {
             get { throw new NotImplementedException(); }
         }
  
         public bool Remove(object item)
         {
             int index = base.IndexOf((T)item);
             if (index >= 0)
             {
                 var res = base.Remove((T)item);
                 RaiseChange(CollectionChange.ItemRemoved, (uint)index);
                 return res;
             }
  
             return false;
         }
  
         private VectorEnumerator<T> _Enum;
         public new IEnumerator<object> GetEnumerator()
         {
             if (_Enum == null)
             {
                 _Enum = new VectorEnumerator<T>(this);
             }
  
             return _Enum;            
         }
     }
  
     public class VectorChangedEventArgs : IVectorChangedEventArgs
     {
         public VectorChangedEventArgs(CollectionChange type, uint index)
         {
             CollectionChange = type;
             Index = index;
         }
         public CollectionChange CollectionChange { get; set; }
         public uint Index { get; set; }
     }
  
     public class VectorEnumerator<T> : IEnumerator<object>
     {
         private IEnumerable<T> _Coll;
         private IEnumerator<T> _Enum;
  
         public VectorEnumerator(IEnumerable<T> internalColl)
         {
             _Coll = internalColl;
             _Enum = _Coll.GetEnumerator();
         }
  
         public object Current
         {
             get { return (object)_Enum.Current; }
         }
  
  
         public bool MoveNext()
         {
             return _Enum.MoveNext();
         }
  
         public void Reset()
         {
             _Enum.Reset();
         }
  
         public void Dispose()
         {
             _Enum.Dispose();
         }
     }
 }