csharp 可观察字典结构模型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 可观察字典结构模型相关的知识,希望对你有一定的参考价值。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
namespace Common
{
public class ViewModelBase : INotifyPropertyChanged, IExtendableViewModel
{
private readonly IDictionary<string, object> _values = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Extend(IEnumerable<KeyValuePair<string, object>> pairs)
{
foreach (var pair in pairs)
Set(pair.Key, pair.Value);
}
protected T Get<T>(Expression<Func<T>> expression)
{
return Get(PropertyName(expression), default(T));
}
private T Get<T>(string name, T defaultValue)
{
if (_values.ContainsKey(name))
{
return (T)_values[name];
}
return defaultValue;
}
protected void Set<T>(Expression<Func<T>> expression, T value)
{
Set(PropertyName(expression), value);
}
private void Set<T>(string name, T value)
{
if (_values.ContainsKey(name))
{
var target = _values[name];
if (target == null && ((!typeof(T).IsPrimitive && value == null) || value.Equals(default(T))))
return;
if (target != null && target.Equals(value))
return;
_values[name] = value;
}
else
{
_values.Add(name, value);
}
OnPropertyChanged(name);
}
protected string PropertyName<T>(Expression<Func<T>> expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
throw new ArgumentException("expression must be a property expression");
return memberExpression.Member.Name;
}
protected void OnPropertyChanged(string propertyName)
{
this.SyncNotify(propertyName, PropertyChanged);
}
protected void OnPropertyChanged<T>(Expression<Func<T>> expression)
{
OnPropertyChanged(PropertyName(expression));
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
namespace Common
{
public class ObservableDictionary<TKey, TValue> : ViewModelBase, IDictionary<TKey, TValue>, INotifyCollectionChanged
{
protected IDictionary<TKey, TValue> Dictionary { get; private set; }
public ObservableDictionary()
{
Dictionary = new Dictionary<TKey, TValue>();
}
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
{
Dictionary = new Dictionary<TKey, TValue>(dictionary);
}
public ObservableDictionary(IEqualityComparer<TKey> comparer)
{
Dictionary = new Dictionary<TKey, TValue>(comparer);
}
public ObservableDictionary(int capacity)
{
Dictionary = new Dictionary<TKey, TValue>(capacity);
}
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
{
Dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
}
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
{
Dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
}
#region IDictionary<TKey,TValue> Members
public void Add(TKey key, TValue value)
{
Update(key, value, true);
}
public bool ContainsKey(TKey key)
{
return Dictionary.ContainsKey(key);
}
ICollection<TKey> IDictionary<TKey, TValue>.Keys
{
get { return Dictionary.Keys; }
}
public bool Remove(TKey key)
{
if (key == null) throw new ArgumentNullException("key");
if (!Dictionary.ContainsKey(key))
throw new ArgumentException("Invalid key", "key");
var removed = Dictionary.Remove(key);
var value = Dictionary[key];
if (removed)
OnCollectionChanged(
NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value));
return removed;
}
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
{
return Dictionary.TryGetValue(key, out value);
}
ICollection<TValue> IDictionary<TKey, TValue>.Values
{
get { return Dictionary.Values; }
}
public TValue this[TKey key]
{
get { return Dictionary[key]; }
set { Update(key, value, false); }
}
#endregion
#region ICollection<KeyValuePair<TKey,TValue>> Members
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
Update(item.Key, item.Value, true);
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
if (Dictionary.Count <= 0) return;
Dictionary.Clear();
OnCollectionChanged(NotifyCollectionChangedAction.Reset);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
return Dictionary.Contains(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
Dictionary.CopyTo(array, arrayIndex);
}
int ICollection<KeyValuePair<TKey, TValue>>.Count
{
get { return Dictionary.Count; }
}
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
{
get { return Dictionary.IsReadOnly; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
#endregion
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return Dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Dictionary).GetEnumerator();
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public void AddRange(IDictionary<TKey, TValue> items)
{
if (items == null) throw new ArgumentNullException("items");
if (items.Count <= 0) return;
if (items.Keys.Any(key => Dictionary.ContainsKey(key)))
throw new ArgumentException("An item with the same key has already been added.");
foreach (var item in items) Dictionary.Add(item);
OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray());
}
private void Update(TKey key, TValue value, bool add)
{
if (key == null) throw new ArgumentNullException("key");
TValue item;
if (!Dictionary.TryGetValue(key, out item))
{
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
return;
}
if (add) throw new ArgumentException("An item with the same key has already been added.");
if (Equals(item, value)) return;
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
}
private void OnPropertyChanged()
{
OnPropertyChanged(PropertyName(() => Dictionary.Count));
OnPropertyChanged(PropertyName(() => Dictionary.Keys));
OnPropertyChanged(PropertyName(() => Dictionary.Values));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action)
{
OnPropertyChanged();
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem)
{
OnPropertyChanged();
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
{
OnPropertyChanged();
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems)
{
OnPropertyChanged();
if (CollectionChanged != null)
CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems));
}
}
}
using System.ComponentModel;
using System.Threading;
using System.Windows.Threading;
namespace Common
{
public static class NotifyPropertyChangedExtensions
{
public static void SyncNotify(this INotifyPropertyChanged host, string propertyName, PropertyChangedEventHandler eventRaiser, bool wait = false, Dispatcher dispatcher = null)
{
dispatcher = dispatcher ?? Dispatcher.CurrentDispatcher;
var args = new PropertyChangedEventArgs(propertyName);
if (eventRaiser == null) return;
if (dispatcher.Thread == Thread.CurrentThread)
{
eventRaiser(host, args);
return;
}
if (wait)
{
dispatcher.Invoke(eventRaiser, host, args);
return;
}
dispatcher.BeginInvoke(eventRaiser, host, args);
}
}
}
using System.Collections.Generic;
namespace Common
{
public interface IExtendableViewModel<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
void Extend(IEnumerable<KeyValuePair<TKey, TValue>> pairs);
}
public interface IExtendableViewModel : IExtendableViewModel<string, object> { }
}
以上是关于csharp 可观察字典结构模型的主要内容,如果未能解决你的问题,请参考以下文章