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();
        }
    }
}