出于历史目的并让人们走上“当前”路径...重要的是要知道 Microsoft 现在在 Visual Studio 2012 的 Windows 应用商店“基本页面”模板中解决了这一要求。为了支持 LayoutAwarePage,他们生成一个私有 ObservableDictionary 类。
但是,他们实现了一个新的 IObservableMap 接口,而不是直接实现 IDictionary。该接口添加了一个 MapChanged 事件和 MapChangedEventHandler,定义在 Windows.Foundation.Collections 命名空间中。
下面的 sn-p 只是你项目的“Common”文件夹中生成的 LayoutAwarePage.cs 中的 ObservableDictionary 类:
/// <summary>
/// Implementation of IObservableMap that supports reentrancy for use as a default view
/// model.
/// </summary>
private class ObservableDictionary<K, V> : IObservableMap<K, V>
{
private class ObservableDictionaryChangedEventArgs : IMapChangedEventArgs<K>
{
public ObservableDictionaryChangedEventArgs(CollectionChange change, K key)
{
CollectionChange = change;
Key = key;
}
public CollectionChange CollectionChange { get; private set; }
public K Key { get; private set; }
}
private Dictionary<K, V> _dictionary = new Dictionary<K, V>();
public event MapChangedEventHandler<K, V> MapChanged;
private void InvokeMapChanged(CollectionChange change, K key)
{
var eventHandler = MapChanged;
if (eventHandler != null)
{
eventHandler(this, new ObservableDictionaryChangedEventArgs(change, key));
}
}
public void Add(K key, V value)
{
_dictionary.Add(key, value);
InvokeMapChanged(CollectionChange.ItemInserted, key);
}
public void Add(KeyValuePair<K, V> item)
{
Add(item.Key, item.Value);
}
public bool Remove(K key)
{
if (_dictionary.Remove(key))
{
InvokeMapChanged(CollectionChange.ItemRemoved, key);
return true;
}
return false;
}
public bool Remove(KeyValuePair<K, V> item)
{
V currentValue;
if (_dictionary.TryGetValue(item.Key, out currentValue) &&
Object.Equals(item.Value, currentValue) && _dictionary.Remove(item.Key))
{
InvokeMapChanged(CollectionChange.ItemRemoved, item.Key);
return true;
}
return false;
}
public V this[K key]
{
get
{
return _dictionary[key];
}
set
{
_dictionary[key] = value;
InvokeMapChanged(CollectionChange.ItemChanged, key);
}
}
public void Clear()
{
var priorKeys = _dictionary.Keys.ToArray();
_dictionary.Clear();
foreach (var key in priorKeys)
{
InvokeMapChanged(CollectionChange.ItemRemoved, key);
}
}
public ICollection<K> Keys
{
get { return _dictionary.Keys; }
}
public bool ContainsKey(K key)
{
return _dictionary.ContainsKey(key);
}
public bool TryGetValue(K key, out V value)
{
return _dictionary.TryGetValue(key, out value);
}
public ICollection<V> Values
{
get { return _dictionary.Values; }
}
public bool Contains(KeyValuePair<K, V> item)
{
return _dictionary.Contains(item);
}
public int Count
{
get { return _dictionary.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException("array");
int arraySize = array.Length;
foreach (var pair in _dictionary)
{
if (arrayIndex >= arraySize) break;
array[arrayIndex++] = pair;
}
}
}
对新的 Windows.Foundation.Collections 命名空间的进一步检查显示定义了许多新接口,但只实现了一个 PropertySet 类。实际上,这似乎是一个非常好的 ObservableDictionary 本身。但是MS仍然生成私有的ObservableDictionary肯定是有原因的。所以这里需要进一步检查以确定利弊。
简而言之,PropertySet 或您自己的基于 IObservableMap 的 ObservableDictionary 应该可以解决“当前”Windows 8 和 Phone 8 项目的即时需求。但是,对于较旧的框架(WPF 4 和 Phone 7.5),还有更多工作要做。