Refactor property changed implementations
This commit is contained in:
@@ -12,7 +12,7 @@ using System.Windows.Threading;
|
||||
namespace Torch.Collections
|
||||
{
|
||||
[Serializable]
|
||||
public class ObservableDictionary<TKey, TValue> : ViewModel, IDictionary<TKey, TValue>, INotifyCollectionChanged
|
||||
public class ObservableDictionary<TKey, TValue> : ViewModel, IDictionary<TKey, TValue>
|
||||
{
|
||||
private IDictionary<TKey, TValue> _internalDict;
|
||||
|
||||
@@ -37,12 +37,6 @@ namespace Torch.Collections
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
@@ -153,26 +147,5 @@ namespace Torch.Collections
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICollection<TValue> Values => _internalDict.Values;
|
||||
|
||||
private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
NotifyCollectionChangedEventHandler collectionChanged = CollectionChanged;
|
||||
if (collectionChanged != null)
|
||||
foreach (NotifyCollectionChangedEventHandler nh in collectionChanged.GetInvocationList())
|
||||
{
|
||||
var dispObj = nh.Target as DispatcherObject;
|
||||
|
||||
var dispatcher = dispObj?.Dispatcher;
|
||||
if (dispatcher != null && !dispatcher.CheckAccess())
|
||||
{
|
||||
dispatcher.BeginInvoke(
|
||||
(Action)(() => nh.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
|
||||
DispatcherPriority.DataBind);
|
||||
continue;
|
||||
}
|
||||
|
||||
nh.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -12,16 +12,10 @@ namespace Torch
|
||||
/// <summary>
|
||||
/// An observable version of <see cref="List{T}"/>.
|
||||
/// </summary>
|
||||
public class ObservableList<T> : IList<T>, INotifyCollectionChanged, INotifyPropertyChanged
|
||||
public class ObservableList<T> : ViewModel, IList<T>
|
||||
{
|
||||
private List<T> _internalList = new List<T>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Clear()
|
||||
{
|
||||
@@ -146,31 +140,6 @@ namespace Torch
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
var collectionChanged = CollectionChanged;
|
||||
if (collectionChanged != null)
|
||||
foreach (var del in collectionChanged.GetInvocationList())
|
||||
{
|
||||
var nh = (NotifyCollectionChangedEventHandler)del;
|
||||
var dispObj = nh.Target as DispatcherObject;
|
||||
|
||||
var dispatcher = dispObj?.Dispatcher;
|
||||
if (dispatcher != null && !dispatcher.CheckAccess())
|
||||
{
|
||||
dispatcher.BeginInvoke(() => nh.Invoke(this, e), DispatcherPriority.DataBind);
|
||||
continue;
|
||||
}
|
||||
|
||||
nh.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
|
@@ -2,6 +2,9 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Torch
|
||||
{
|
||||
@@ -37,6 +40,63 @@ namespace Torch
|
||||
return source as IReadOnlyDictionary<TKey, TValue> ?? new ReadOnlyDictionary<TKey, TValue>(source);
|
||||
}
|
||||
|
||||
public static IReadOnlyDictionary<TKey, TValue> AsReadOnlyObservable<TKey, TValue>(this IDictionary<TKey, TValue> source)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
return new ObservableReadOnlyDictionary<TKey, TValue>(source);
|
||||
}
|
||||
|
||||
sealed class ObservableReadOnlyDictionary<TKey, TValue> : ViewModel, IReadOnlyDictionary<TKey, TValue>
|
||||
{
|
||||
private readonly IDictionary<TKey, TValue> _dictionary;
|
||||
|
||||
public ObservableReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
_dictionary = dictionary;
|
||||
|
||||
if (_dictionary is INotifyPropertyChanged p)
|
||||
p.PropertyChanged += OnPropertyChanged;
|
||||
|
||||
if (_dictionary is INotifyCollectionChanged c)
|
||||
c.CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnCollectionChanged(e);
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(e.PropertyName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _dictionary.GetEnumerator();
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_dictionary).GetEnumerator();
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => _dictionary.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ContainsKey(TKey key) => _dictionary.ContainsKey(key);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(TKey key, out TValue value) => _dictionary.TryGetValue(key, out value);
|
||||
|
||||
/// <inheritdoc />
|
||||
public TValue this[TKey key] => _dictionary[key];
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TKey> Keys => _dictionary.Keys;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TValue> Values => _dictionary.Values;
|
||||
}
|
||||
|
||||
sealed class ReadOnlyCollectionAdapter<T> : IReadOnlyCollection<T>
|
||||
{
|
||||
private readonly ICollection<T> _source;
|
||||
|
@@ -7,21 +7,47 @@ using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Torch
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a method to notify an observer of changes to an object's properties.
|
||||
/// </summary>
|
||||
public abstract class ViewModel : INotifyPropertyChanged
|
||||
public abstract class ViewModel : INotifyPropertyChanged, INotifyCollectionChanged
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propName = "")
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
|
||||
}
|
||||
|
||||
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
NotifyCollectionChangedEventHandler collectionChanged = CollectionChanged;
|
||||
if (collectionChanged != null)
|
||||
foreach (NotifyCollectionChangedEventHandler nh in collectionChanged.GetInvocationList())
|
||||
{
|
||||
var dispObj = nh.Target as DispatcherObject;
|
||||
|
||||
var dispatcher = dispObj?.Dispatcher;
|
||||
if (dispatcher != null && !dispatcher.CheckAccess())
|
||||
{
|
||||
dispatcher.BeginInvoke(
|
||||
(Action)(() => nh.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
|
||||
DispatcherPriority.DataBind);
|
||||
continue;
|
||||
}
|
||||
|
||||
nh.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetValue<T>(ref T backingField, T value, [CallerMemberName] string propName = "")
|
||||
{
|
||||
if (backingField.Equals(value))
|
||||
|
Reference in New Issue
Block a user