实现一个ObservableDictionary

.NET Framework 4仍没有提供ObservableDictionary类型,如果不实现字典的特性,完全可以用一个简单的包含Key和Value属性的类的ObservableCollection实现。

一个ObservableDictionary应该实现这些接口(参考:《Can I bind my ItemsControl to a dictionary?》):

IDictionary<TKey TValue>
ICollection<KeyValuePair<TKey TValue>>
IEnumerable<KeyValuePair<TKey TValue>>
IDictionary
ICollection
IEnumerable
ISerializable
IDeserializationCallback
INotifyCollectionChanged
INotifyPropertyChanged

看来需要实现的成员会很多,我没有使用封装的办法,而是直接继承了Dictionary<TKey, TValue>,代码:

// ----------------------------------------
// ObservableDictionary.cs
// ----------------------------------------

using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.Serialization;

/// <summary>
/// ObservableDictionary的实现(oyi319)
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class ObservableDictionary<TKey, TValue> :
	Dictionary<TKey, TValue>,
	IDictionary<TKey, TValue>,
	IDictionary,
	INotifyCollectionChanged,
	INotifyPropertyChanged
{
	#region 构造

	public ObservableDictionary()
	{
	}

	public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
		: base(dictionary)
	{
	}

	public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
		: base(dictionary, comparer)
	{
	}

	public ObservableDictionary(IEqualityComparer<TKey> comparer)
		: base(comparer)
	{
	}

	public ObservableDictionary(int capacity)
		: base(capacity)
	{
	}

	public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
		: base(capacity, comparer)
	{
	}

	public ObservableDictionary(SerializationInfo info, StreamingContext context)
		: base(info, context)
	{
	}

	#endregion

	#region 方法

	private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
	{
		if (this.CollectionChanged != null)
		{
			this.CollectionChanged(this, args);
		}
	}

	private void OnPropertyChanged(string propertyName)
	{
		if (this.PropertyChanged != null)
		{
			this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}

	}

	#endregion

	#region 重载

	void IDictionary.Clear()
	{
		if (base.Count > 0)
		{
			base.Clear();

			this.OnPropertyChanged("Keys");
			this.OnPropertyChanged("Values");
			this.OnPropertyChanged("Count");
			this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
		}
	}

	public void Remove(object key)
	{
		var k = (TKey)key;
		if (!base.ContainsKey(k))
		{
			return; //不包含的
		}

		var v = base[k];
		var item = new KeyValuePair<TKey, TValue>(k, v);

		base.Remove(k);

		this.OnPropertyChanged("Keys");
		this.OnPropertyChanged("Values");
		this.OnPropertyChanged("Count");
		this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
	}

	object IDictionary.this[object key]
	{
		get
		{
			return base[(TKey)key];
		}
		set
		{
			var k = (TKey)key;

			if (base.ContainsKey(k))
			{
				var v = base[k];
				if (v.Equals((TValue)value))
				{
					return;
				}

				var newitem = new KeyValuePair<TKey, TValue>(k, (TValue)value);
				var oldItem = new KeyValuePair<TKey, TValue>(k, base[k]);
				base[k] = newitem.Value;

				this.OnPropertyChanged("Values");
				this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(
											 NotifyCollectionChangedAction.Replace,
											 newitem,
											 oldItem));
				return;
			}

			var item = new KeyValuePair<TKey, TValue>(k, (TValue)value);
			base.Add(k, item.Value);
			this.OnPropertyChanged("Keys");
			this.OnPropertyChanged("Values");
			this.OnPropertyChanged("Count");
			this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
		}
	}

	public void Add(KeyValuePair<TKey, TValue> item)
	{
		base.Add(item.Key, item.Value);
		this.OnPropertyChanged("Keys");
		this.OnPropertyChanged("Values");
		this.OnPropertyChanged("Count");
		this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
	}

	public void Add(object key, object value)
	{
		var item = new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
		base.Add(item.Key, item.Value);
		this.OnPropertyChanged("Keys");
		this.OnPropertyChanged("Values");
		this.OnPropertyChanged("Count");
		this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
	}

	void ICollection<KeyValuePair<TKey, TValue>>.Clear()
	{
		((IDictionary)this).Clear();
	}

	public bool Remove(KeyValuePair<TKey, TValue> item)
	{
		if (!base.ContainsKey(item.Key))
		{
			return false;
		}

		var r = base.Remove(item.Key);
		this.OnPropertyChanged("Keys");
		this.OnPropertyChanged("Values");
		this.OnPropertyChanged("Count");
		this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
		return r;
	}

	public new void Add(TKey key, TValue value)
	{
		var item = new KeyValuePair<TKey, TValue>(key, value);
		base.Add(item.Key, item.Value);
		this.OnPropertyChanged("Keys");
		this.OnPropertyChanged("Values");
		this.OnPropertyChanged("Count");
		this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
	}

	public new bool Remove(TKey key)
	{
		if (base.ContainsKey(key))
			return false;

		var v = base[key];
		var item = new KeyValuePair<TKey, TValue>(key, v);

		var r = base.Remove(key);

		this.OnPropertyChanged("Keys");
		this.OnPropertyChanged("Values");
		this.OnPropertyChanged("Count");
		this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
		return r;
	}

	TValue IDictionary<TKey, TValue>.this[TKey key]
	{
		get { return base[key]; }
		set
		{
			if(base.ContainsKey(key))
			{
				var v = base[key];
				if(v.Equals(value))
				{
					return;
				}

				var newitem = new KeyValuePair<TKey, TValue>(key, value);
				var oldItem = new KeyValuePair<TKey, TValue>(key, base[key]);
				base[key] = newitem.Value;

				this.OnPropertyChanged("Values");
				this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(
											 NotifyCollectionChangedAction.Replace,
											 newitem,
											 oldItem));
				return;
			}

			var item = new KeyValuePair<TKey, TValue>(key, value);
			base.Add(key, item.Value);
			this.OnPropertyChanged("Keys");
			this.OnPropertyChanged("Values");
			this.OnPropertyChanged("Count");
			this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
		}
	}

	public event NotifyCollectionChangedEventHandler CollectionChanged;
	public event PropertyChangedEventHandler PropertyChanged;

	#endregion
}

注:代码有待完善,请谨慎使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值