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