Skip to content

Commit

Permalink
INotifyCollectionChangedSynchronizedViewList -> NotifyCollectionChang…
Browse files Browse the repository at this point in the history
…edSynchronizedViewList
  • Loading branch information
neuecc committed Oct 16, 2024
1 parent 8afb3fb commit 7987d75
Show file tree
Hide file tree
Showing 9 changed files with 442 additions and 634 deletions.
2 changes: 1 addition & 1 deletion sandbox/ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
var view = list.CreateWritableView(x => x.Name);
view.AttachFilter(x => x.Age >= 20);

IList<string?> bindable = view.ToWritableNotifyCollectionChanged((string? newView, Person original, ref bool setValue) =>
var bindable = view.ToWritableNotifyCollectionChanged((string? newView, Person original, ref bool setValue) =>
{
if (setValue)
{
Expand Down
101 changes: 94 additions & 7 deletions src/ObservableCollections/IObservableCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public interface ISynchronizedView<T, TView> : IReadOnlyCollection<TView>, IDisp
void AttachFilter(ISynchronizedViewFilter<T> filter);
void ResetFilter();
ISynchronizedViewList<TView> ToViewList();
INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged();
INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher);
NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged();
NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher);
}

public interface IWritableSynchronizedView<T, TView> : ISynchronizedView<T, TView>
Expand All @@ -58,9 +58,9 @@ public interface IWritableSynchronizedView<T, TView> : ISynchronizedView<T, TVie
void SetToSourceCollection(int index, T value);
void AddToSourceCollection(T value);
IWritableSynchronizedViewList<TView> ToWritableViewList(WritableViewChangedEventHandler<T, TView> converter);
INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter);
INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher);
INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter, ICollectionEventDispatcher? collectionEventDispatcher);
NotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter);
NotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher);
NotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter, ICollectionEventDispatcher? collectionEventDispatcher);
}

public interface ISynchronizedViewList<out TView> : IReadOnlyList<TView>, IDisposable
Expand All @@ -72,10 +72,97 @@ public interface IWritableSynchronizedViewList<TView> : ISynchronizedViewList<TV
new TView this[int index] { get; set; }
}

// only for compatibility, use NotifyCollectionChangedSynchronizedViewList insetad.
// [Obsolete] in future
public interface INotifyCollectionChangedSynchronizedViewList<TView> : IList<TView>, IList, ISynchronizedViewList<TView>, INotifyCollectionChanged, INotifyPropertyChanged
{
}

// IColleciton<T>.Count and ICollection.Count will be ambigious so use abstract class instead of interface
public abstract class NotifyCollectionChangedSynchronizedViewList<TView> :
INotifyCollectionChangedSynchronizedViewList<TView>,
IWritableSynchronizedViewList<TView>,
IList<TView>,
IList
{
protected readonly object gate = new object();

public abstract TView this[int index] { get; set; }

object? IList.this[int index]
{
get
{
return this[index];
}
set => ((IList<TView>)this)[index] = (TView)value!;
}

public abstract int Count { get; }
public bool IsReadOnly => false;
public bool IsFixedSize => false;
public bool IsSynchronized => true;
public object SyncRoot => gate;

public abstract event NotifyCollectionChangedEventHandler? CollectionChanged;
public abstract event PropertyChangedEventHandler? PropertyChanged;

public abstract void Add(TView item);

int IList.Add(object? value)
{
Add((TView)value!);
return -1; // itself does not add in this collection
}

public abstract bool Contains(TView item);

bool IList.Contains(object? value)
{
if (IsCompatibleObject(value))
{
return Contains((TView)value!);
}
return false;
}

public abstract void Dispose();
public abstract IEnumerator<TView> GetEnumerator();
public abstract int IndexOf(TView item);

int IList.IndexOf(object? item)
{
if (IsCompatibleObject(item))
{
return IndexOf((TView)item!);
}
return -1;
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

static bool IsCompatibleObject(object? value)
{
return value is TView || value == null && default(TView) == null;
}

void ICollection<TView>.Clear() => throw new NotSupportedException();
void IList.Clear() => throw new NotSupportedException();

void ICollection<TView>.CopyTo(TView[] array, int arrayIndex) => throw new NotSupportedException();
void ICollection.CopyTo(Array array, int index) => throw new NotSupportedException();

void IList<TView>.Insert(int index, TView item) => throw new NotSupportedException();
void IList.Insert(int index, object? value) => throw new NotSupportedException();
bool ICollection<TView>.Remove(TView item) => throw new NotSupportedException();
void IList.Remove(object? value) => throw new NotSupportedException();
void IList.RemoveAt(int index) => throw new NotSupportedException();
void IList<TView>.RemoveAt(int index) => throw new NotSupportedException();
}

public static class ObservableCollectionExtensions
{
public static ISynchronizedViewList<T> ToViewList<T>(this IObservableCollection<T> collection)
Expand All @@ -86,7 +173,7 @@ public static ISynchronizedViewList<T> ToViewList<T>(this IObservableCollection<
public static ISynchronizedViewList<TView> ToViewList<T, TView>(this IObservableCollection<T> collection, Func<T, TView> transform)
{
// Optimized for non filtered
return new NonFilteredSynchronizedViewList<T, TView>(collection.CreateView(transform));
return new NonFilteredSynchronizedViewList<T, TView>(collection.CreateView(transform), isSupportRangeFeature: true, null, null);
}

public static INotifyCollectionChangedSynchronizedViewList<T> ToNotifyCollectionChanged<T>(this IObservableCollection<T> collection)
Expand All @@ -107,7 +194,7 @@ public static INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollec
public static INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged<T, TView>(this IObservableCollection<T> collection, Func<T, TView> transform, ICollectionEventDispatcher? collectionEventDispatcher)
{
// Optimized for non filtered
return new NonFilteredNotifyCollectionChangedSynchronizedViewList<T, TView>(collection.CreateView(transform), collectionEventDispatcher);
return new NonFilteredSynchronizedViewList<T, TView>(collection.CreateView(transform), isSupportRangeFeature: false, collectionEventDispatcher, null);
}
}
}
10 changes: 5 additions & 5 deletions src/ObservableCollections/ObservableDictionary.Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,17 @@ public void ResetFilter()

public ISynchronizedViewList<TView> ToViewList()
{
return new FiltableSynchronizedViewList<KeyValuePair<TKey, TValue>, TView>(this);
return new FiltableSynchronizedViewList<KeyValuePair<TKey, TValue>, TView>(this, isSupportRangeFeature: true);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
{
return new NotifyCollectionChangedSynchronizedViewList<KeyValuePair<TKey, TValue>, TView>(this, null);
return new FiltableSynchronizedViewList<KeyValuePair<TKey, TValue>, TView>(this, isSupportRangeFeature: false);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NotifyCollectionChangedSynchronizedViewList<KeyValuePair<TKey, TValue>, TView>(this, collectionEventDispatcher);
return new FiltableSynchronizedViewList<KeyValuePair<TKey, TValue>, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
}

public IEnumerator<TView> GetEnumerator()
Expand Down
10 changes: 5 additions & 5 deletions src/ObservableCollections/ObservableHashSet.Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,17 @@ public void ResetFilter()

public ISynchronizedViewList<TView> ToViewList()
{
return new FiltableSynchronizedViewList<T, TView>(this);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, null);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
}

public IEnumerator<TView> GetEnumerator()
Expand Down
38 changes: 20 additions & 18 deletions src/ObservableCollections/ObservableList.Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyColle

public INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged<TView>(Func<T, TView> transform, WritableViewChangedEventHandler<T, TView>? converter, ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NonFilteredNotifyCollectionChangedSynchronizedViewList<T, TView>(CreateView(transform), collectionEventDispatcher, converter);
return new NonFilteredSynchronizedViewList<T, TView>(CreateView(transform), isSupportRangeFeature: false, collectionEventDispatcher, converter);
}

internal sealed class View<TView> : ISynchronizedView<T, TView>, IWritableSynchronizedView<T, TView>
Expand Down Expand Up @@ -141,17 +141,17 @@ public void ResetFilter()

public ISynchronizedViewList<TView> ToViewList()
{
return new FiltableSynchronizedViewList<T, TView>(this);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, null);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
}

public IEnumerator<TView> GetEnumerator()
Expand Down Expand Up @@ -370,27 +370,29 @@ public void AddToSourceCollection(T value)

public IWritableSynchronizedViewList<TView> ToWritableViewList(WritableViewChangedEventHandler<T, TView> converter)
{
return new FiltableWritableSynchronizedViewList<T, TView>(this, converter);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true, converter: converter);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter)
public NotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, null, converter);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, converter: converter);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher,
static (TView newView, T originalValue, ref bool setValue) =>
{
setValue = true;
return originalValue;
});
return new FiltableSynchronizedViewList<T, TView>(this,
isSupportRangeFeature: false,
collectionEventDispatcher,
static (TView newView, T originalValue, ref bool setValue) =>
{
setValue = true;
return originalValue;
});
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter, ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToWritableNotifyCollectionChanged(WritableViewChangedEventHandler<T, TView> converter, ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher, converter);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher, converter);
}

#endregion
Expand Down
10 changes: 5 additions & 5 deletions src/ObservableCollections/ObservableQueue.Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,17 @@ public void ResetFilter()

public ISynchronizedViewList<TView> ToViewList()
{
return new FiltableSynchronizedViewList<T, TView>(this);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, null);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
}

public IEnumerator<TView> GetEnumerator()
Expand Down
10 changes: 5 additions & 5 deletions src/ObservableCollections/ObservableRingBuffer.Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,22 @@ public void ResetFilter()

public ISynchronizedViewList<TView> ToViewList()
{
return new FiltableSynchronizedViewList<T, TView>(this);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, null);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false);
}
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
lock (SyncRoot)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/ObservableCollections/ObservableStack.Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,22 @@ public void ResetFilter()

public ISynchronizedViewList<TView> ToViewList()
{
return new FiltableSynchronizedViewList<T, TView>(this);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true);
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, null);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false);
}
}

public INotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
{
lock (SyncRoot)
{
return new NotifyCollectionChangedSynchronizedViewList<T, TView>(this, collectionEventDispatcher);
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
}
}

Expand Down
Loading

0 comments on commit 7987d75

Please sign in to comment.