< Summary

Information
Class: MyNet.Observable.Collections.ExtendedCollection<T>
Assembly: MyNet.Observable
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Observable/Collections/ExtendedCollection.cs
Tag: 323_28699572109
Line coverage
88%
Covered lines: 100
Uncovered lines: 13
Coverable lines: 113
Total lines: 498
Line coverage: 88.4%
Branch coverage
87%
Covered branches: 14
Total branches: 16
Branch coverage: 87.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Observable/Collections/ExtendedCollection.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="ExtendedCollection.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections;
 9using System.Collections.Generic;
 10using System.Collections.ObjectModel;
 11using System.Collections.Specialized;
 12using System.ComponentModel;
 13using System.Diagnostics;
 14using System.Diagnostics.CodeAnalysis;
 15using System.Reactive.Concurrency;
 16using System.Reactive.Disposables;
 17using System.Reactive.Linq;
 18using System.Runtime.InteropServices;
 19using DynamicData;
 20using MyNet.Observable.Collections.Filters;
 21using MyNet.Observable.Collections.Grouping;
 22using MyNet.Observable.Collections.Paging;
 23using MyNet.Observable.Collections.Sorting;
 24using MyNet.Observable.Collections.Sources;
 25using MyNet.Primitives;
 26
 27namespace MyNet.Observable.Collections;
 28
 29/// <summary>
 30/// Provides factory methods for creating instances of the <see cref="ExtendedCollection{T}"/> class. The <see cref="Ext
 31/// </summary>
 32[SuppressMessage("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "This class serves as 
 33public static class ExtendedCollection
 34{
 35    /// <summary>
 36    /// Creates a new instance of the <see cref="ExtendedCollection{T}"/> class with an optional scheduler for observing
 37    /// </summary>
 38    /// <param name="scheduler">The scheduler on which the collection's operations will be performed.</param>
 39    /// <typeparam name="T">The type of items managed by the extended collection.</typeparam>
 40    /// <returns>The created <see cref="ExtendedCollection{T}"/> instance.</returns>
 41    public static ExtendedCollection<T> Create<T>(IScheduler? scheduler = null)
 42        where T : notnull
 43        => new(SourceEngine<T>.Empty(), scheduler);
 44
 45    /// <summary>
 46    /// Creates a new instance of the <see cref="ExtendedCollection{T}"/> class from an existing enumerable collection o
 47    /// </summary>
 48    /// <param name="items">The enumerable collection of items to initialize the extended collection with.</param>
 49    /// <param name="scheduler">The scheduler on which the collection's operations will be performed.</param>
 50    /// <typeparam name="T">The type of items managed by the extended collection.</typeparam>
 51    /// <returns>The created <see cref="ExtendedCollection{T}"/> instance.</returns>
 52    public static ExtendedCollection<T> From<T>(IEnumerable<T> items, IScheduler? scheduler = null)
 53        where T : notnull
 54        => new(SourceEngine<T>.From(items, readOnly: false), scheduler);
 55
 56    /// <summary>
 57    /// Creates a new instance of the <see cref="ExtendedCollection{T}"/> class from an existing enumerable collection o
 58    /// </summary>
 59    /// <param name="items">The enumerable collection of items to initialize the extended collection with.</param>
 60    /// <param name="scheduler">The scheduler on which the collection's operations will be performed.</param>
 61    /// <typeparam name="T">The type of items managed by the extended collection.</typeparam>
 62    /// <returns>The created <see cref="ExtendedCollection{T}"/> instance.</returns>
 63    public static ExtendedCollection<T> FromReadOnly<T>(IEnumerable<T> items, IScheduler? scheduler = null)
 64        where T : notnull
 65        => new(SourceEngine<T>.From(items, readOnly: true), scheduler);
 66
 67    /// <summary>
 68    /// Creates a new instance of the <see cref="ExtendedCollection{T}"/> class from an observable sequence of change se
 69    /// </summary>
 70    /// <param name="source">The observable sequence of change sets to initialize the extended collection with.</param>
 71    /// <param name="scheduler">The scheduler on which the collection's operations will be performed.</param>
 72    /// <typeparam name="T">The type of items managed by the extended collection.</typeparam>
 73    /// <returns>The created <see cref="ExtendedCollection{T}"/> instance.</returns>
 74    public static ExtendedCollection<T> FromObservable<T>(IObservable<IChangeSet<T>> source, IScheduler? scheduler = nul
 75        where T : notnull
 76        => new(SourceEngine<T>.FromObservable(source), scheduler);
 77}
 78
 79/// <summary>
 80/// Represents an extended collection that supports filtering, sorting, and change notifications. This collection is des
 81/// </summary>
 82/// <typeparam name="T">The type of items managed by the extended collection.</typeparam>
 83[ComVisible(false)]
 84[DebuggerDisplay("Count = {Count}/{SourceCount}")]
 85[SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "Disposed in DisposeManagedReso
 86public class ExtendedCollection<T> : ObservableObject, ICollection<T>, IReadOnlyList<T>, INotifyCollectionChanged
 87    where T : notnull
 88{
 89    private readonly SourceEngine<T> _source;
 18690    private readonly FilterEngine<T> _filterEngine = new();
 18691    private readonly SortEngine<T> _sortEngine = new();
 18692    private readonly GroupingEngine<T> _groupingEngine = new();
 18693    private readonly PagingEngine _pagingEngine = new();
 18694    private readonly PropertyDependencyExtractor<T> _dependencyExtractor = new();
 95
 96    private readonly IObservable<IChangeSet<T>> _filteredObservable;
 97    private readonly IObservable<IChangeSet<T>> _itemsObservable;
 98    private readonly IObservable<IChangeSet<T>> _sourceObservable;
 99    private readonly ReadOnlyObservableCollection<T> _filteredItems;
 100    private readonly ReadOnlyObservableCollection<T> _items;
 101    private readonly ReadOnlyObservableCollection<T> _sortedSource;
 102    private readonly IObservable<IReadOnlyList<CollectionGroup<T>>> _groupsObservable;
 186103    private readonly Dictionary<string, int> _filterPropertyUsage = [];
 186104    private readonly Dictionary<string, int> _sortPropertyUsage = [];
 105    private int _count;
 106    private int _sourceCount;
 107
 108    /// <summary>
 109    /// Initializes a new instance of the <see cref="ExtendedCollection{T}"/> class with a specified source list, read-o
 110    /// </summary>
 111    /// <param name="source">The source list to initialize the collection with.</param>
 112    /// <param name="scheduler">The scheduler to use for observing collection changes. If null, the current thread sched
 186113    public ExtendedCollection(SourceEngine<T> source, IScheduler? scheduler = null)
 114    {
 186115        _source = source;
 186116        IsReadOnly = source.IsReadOnly;
 117
 186118        (_sourceObservable, _filteredObservable) = PipelineEngine.Build(_source.Connect(), _filterEngine, _sortEngine);
 186119        _itemsObservable = PipelineEngine.ApplyPaging(_filteredObservable, _pagingEngine);
 120
 121        // Groups observable: recomputed reactively whenever filtered items or grouping config changes
 186122        _groupsObservable = _filteredObservable.ToCollection()
 186123            .CombineLatest(
 186124                _groupingEngine.Grouping,
 186125                (items, grouping) => GroupingEngine<T>.ComputeGroups([.. items], grouping));
 126
 127        Disposables.Add(_sourceObservable.ObserveOnOptional(scheduler).Bind(out _sortedSource).Subscribe(_ => UpdateSour
 128        Disposables.Add(_filteredObservable.ObserveOnOptional(scheduler).Bind(out _filteredItems).Subscribe(_ => UpdateF
 186129        Disposables.Add(_itemsObservable.ObserveOnOptional(scheduler).Bind(out _items).Subscribe());
 186130        Disposables.Add(_source.Connect().SubscribeMany(SubscribeToItemChanges).Subscribe());
 186131        Disposables.Add(ObserveCollectionChanges(_items).Subscribe(HandleCollectionChanged));
 132
 186133        UpdateSourceCount();
 186134        UpdateFilteredCount();
 186135    }
 136
 137    /// <summary>
 138    /// Gets a read-only observable collection of items after applying filters and sorting, before paging.
 139    /// </summary>
 72140    public ReadOnlyObservableCollection<T> FilteredItems => _filteredItems;
 141
 142    /// <summary>
 143    /// Gets a read-only observable collection of items that represents the current page after applying filters, sorting
 144    /// </summary>
 126145    public ReadOnlyObservableCollection<T> Items => _items;
 146
 147    /// <summary>
 148    /// Gets a read-only observable collection of items that represents the current state of the source collection after
 149    /// </summary>
 63150    public ReadOnlyObservableCollection<T> Source => _sortedSource;
 151
 152    /// <summary>
 153    /// Gets the count of items in the source collection after sorting but before filtering. This count reflects the num
 154    /// </summary>
 66155    public int SourceCount => _sourceCount;
 156
 157    /// <summary>
 158    /// Gets the collection of sorting properties that are applied to the items in the collection. The Sorting property 
 159    /// </summary>
 0160    public ISortingProperty<T>[] CurrentSort => _sortEngine.Current;
 161
 162    /// <summary>
 163    /// Gets the collection of filters that are applied to the items in the collection. The Filters property allows you 
 164    /// </summary>
 0165    public IFilter<T>? CurrentFilter => _filterEngine.Current;
 166
 167    /// <summary>
 168    /// Observes item changes after filter/sort operations, before paging is applied.
 169    /// </summary>
 12170    public IObservable<IChangeSet<T>> ConnectFiltered() => _filteredObservable;
 171
 172    /// <summary>
 173    /// Connects to the collection and returns an observable sequence of change sets representing the changes to the ite
 174    /// </summary>
 54175    public IObservable<IChangeSet<T>> Connect() => _itemsObservable;
 176
 177    /// <summary>
 178    /// Connects to the source collection and returns an observable sequence of change sets representing the changes to 
 179    /// </summary>
 0180    public IObservable<IChangeSet<T>> ConnectSource() => _sourceObservable;
 181
 182    /// <summary>
 183    /// Performs cleanup of resources used by the collection, including disposing of the filter engine, sort engine, and
 184    /// </summary>
 185    protected override void DisposeManagedResources()
 186    {
 156187        _filterEngine.Dispose();
 156188        _sortEngine.Dispose();
 156189        _groupingEngine.Dispose();
 156190        _pagingEngine.Dispose();
 156191        _source.Dispose();
 192
 156193        base.DisposeManagedResources();
 156194    }
 195
 196    #region Grouping
 197
 198    /// <summary>
 199    /// Gets the currently active grouping properties applied to the collection.
 200    /// </summary>
 0201    public IGroupingProperty<T>[] CurrentGrouping => _groupingEngine.Current;
 202
 203    /// <summary>
 204    /// Returns an observable sequence that emits the current groups whenever the items or grouping configuration change
 205    /// Emits an empty list when no grouping is active.
 206    /// </summary>
 69207    public IObservable<IReadOnlyList<CollectionGroup<T>>> ConnectGroups() => _groupsObservable;
 208
 209    /// <summary>
 210    /// Sets the grouping properties for the collection. The collection will reactively recompute its groups.
 211    /// </summary>
 212    /// <param name="grouping">The grouping properties to apply.</param>
 6213    public void SetGrouping(params IGroupingProperty<T>[] grouping) => _groupingEngine.Set(grouping);
 214
 215    /// <summary>
 216    /// Clears all grouping properties, producing an empty groups list.
 217    /// </summary>
 78218    public void ClearGrouping() => _groupingEngine.Clear();
 219
 220    #endregion
 221
 222    #region Filter
 223
 224    /// <summary>
 225    /// Sets the filter for the collection using the specified filter node. This method updates the filter engine with t
 226    /// </summary>
 227    /// <param name="filter">The filter to apply to the collection.</param>
 228    public void SetFilter(IFilter<T> filter)
 229    {
 42230        _filterEngine.Set(filter);
 42231        RebuildFilterDependencies(filter);
 42232    }
 233
 234    /// <summary>
 235    /// Clears the filter from the collection, effectively removing all filtering criteria and including all items in th
 236    /// </summary>
 237    public void ClearFilter()
 238    {
 3239        _filterEngine.Clear();
 3240        _filterPropertyUsage.Clear();
 3241    }
 242
 243    #endregion
 244
 245    #region Sorting
 246
 247    /// <summary>
 248    /// Sets the sorting properties for the collection using the specified array of sorting properties. This method upda
 249    /// </summary>
 250    /// <param name="sorting">The array of sorting properties to apply to the collection.</param>
 251    public void SetSorting(params ISortingProperty<T>[] sorting)
 252    {
 21253        _sortEngine.Set(sorting);
 21254        RebuildSortDependencies(sorting);
 21255    }
 256
 257    /// <summary>
 258    /// Clears the sorting properties from the collection, effectively removing all sorting criteria and returning to th
 259    /// </summary>
 260    public void ClearSorting()
 261    {
 75262        _sortEngine.Clear();
 75263        _sortPropertyUsage.Clear();
 75264    }
 265
 266    #endregion
 267
 268    #region Paging
 269
 270    /// <summary>
 271    /// Sets the active paging window applied to the filtered and sorted items exposed through <see cref="Items"/>.
 272    /// </summary>
 273    /// <param name="page">The one-based page index.</param>
 274    /// <param name="pageSize">The page size.</param>
 60275    public void SetPaging(int page, int pageSize) => _pagingEngine.Set(page, pageSize);
 276
 277    /// <summary>
 278    /// Clears paging and exposes the full filtered and sorted collection through <see cref="Items"/>.
 279    /// </summary>
 54280    public void ClearPaging() => _pagingEngine.Clear();
 281
 282    #endregion
 283
 284    #region INotifyCollectionChanged
 285
 286    /// <summary>
 287    /// Occurs when the collection changes. This event is raised whenever items are added, removed, or replaced in the c
 288    /// </summary>
 289    [SuppressMessage("Design", "CA1033:Interface methods should be callable by child types", Justification = "Use OnColl
 290    event NotifyCollectionChangedEventHandler? INotifyCollectionChanged.CollectionChanged
 291    {
 33292        add => CollectionChanged += value;
 3293        remove => CollectionChanged -= value;
 294    }
 295
 296    /// <summary>
 297    /// Raises the CollectionChanged event with the specified event arguments. This method is called internally to notif
 298    /// </summary>
 299    [SuppressMessage("Roslynator", "RCS1159:Use EventHandler<T>", Justification = "Use OnCollectionChanged")]
 300    private event NotifyCollectionChangedEventHandler? CollectionChanged;
 301
 302    /// <summary>
 303    /// Handles the collection changed event by invoking the CollectionChanged event with the provided event arguments. 
 304    /// </summary>
 305    /// <param name="e">The event arguments describing the change that occurred in the collection.</param>
 522306    private void HandleCollectionChanged(NotifyCollectionChangedEventArgs e) => CollectionChanged?.Invoke(this, e);
 307
 308    #endregion INotifyCollectionChanged
 309
 310    #region ICollection
 311
 312    /// <summary>
 313    /// Gets the number of items in the collection after filtering and sorting are applied, before paging.
 314    /// </summary>
 354315    public int Count => _count;
 316
 317    /// <summary>
 318    /// Gets a value indicating whether the collection is read-only. If true, the collection does not allow modification
 319    /// </summary>
 320    public bool IsReadOnly { get; }
 321
 322    /// <summary>
 323    /// Gets the item at the specified index in the collection after filtering and sorting are applied. This index is ba
 324    /// </summary>
 325    /// <param name="index">The zero-based index of the item to get.</param>
 326    /// <returns>The item at the specified index.</returns>
 0327    public T this[int index] => _items[index];
 328
 329    /// <summary>
 330    /// Adds an item to the collection if it is not read-only. This method checks the IsReadOnly property before attempt
 331    /// </summary>
 332    /// <param name="item">The item to add to the collection.</param>
 6333    public void Add(T item) => IsReadOnly.IfFalse(() => _source.Add(item));
 334
 335    /// <summary>
 336    /// Removes all items from the collection if it is not read-only. This method checks the IsReadOnly property before 
 337    /// </summary>
 3338    public void Clear() => IsReadOnly.IfFalse(() => _source.Clear());
 339
 340    /// <summary>
 341    /// Removes the first occurrence of a specific item from the collection if it is not read-only. This method checks t
 342    /// </summary>
 343    /// <param name="item">The item to remove from the collection.</param>
 344    /// <returns>True if the item was successfully removed; otherwise, false.</returns>
 3345    public bool Remove(T item) => !IsReadOnly && _source.Remove(item);
 346
 347    /// <summary>
 348    /// Determines the index of a specific item in the collection after filtering and sorting are applied. This method s
 349    /// </summary>
 350    /// <param name="item">The item to locate in the collection.</param>
 351    /// <returns>The index of the item if found; otherwise, -1.</returns>
 0352    public int IndexOf(T item) => _items.IndexOf(item);
 353
 354    /// <summary>
 355    /// Determines whether the collection contains a specific item after filtering is applied. This method checks for th
 356    /// </summary>
 357    /// <param name="item">The item to locate in the collection.</param>
 358    /// <returns>True if the item is found in the collection; otherwise, false.</returns>
 3359    public bool Contains(T item) => _items.Contains(item);
 360
 361    /// <summary>
 362    /// Copies the elements of the collection to an array, starting at a particular array index. This method allows you 
 363    /// </summary>
 364    /// <param name="array">The destination array.</param>
 365    /// <param name="arrayIndex">The zero-based index in the array at which copying begins.</param>
 6366    public void CopyTo(T[] array, int arrayIndex) => _items.CopyTo(array, arrayIndex);
 367
 368    /// <summary>
 369    /// Returns an enumerator that iterates through the collection. This method allows you to use foreach loops or LINQ 
 370    /// </summary>
 371    /// <returns>An enumerator that can be used to iterate through the collection.</returns>
 12372    public IEnumerator<T> GetEnumerator() => _items.GetEnumerator();
 373
 374    /// <summary>
 375    /// Returns an enumerator that iterates through the collection. This method is an explicit implementation of the non
 376    /// </summary>
 377    /// <returns>An enumerator that can be used to iterate through the collection.</returns>
 3378    IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();
 379
 380    #endregion
 381
 382    #region ICollection Extensions
 383
 384    /// <summary>
 385    /// Adds multiple items to the collection if it is not read-only. This method checks the IsReadOnly property before 
 386    /// </summary>
 387    /// <param name="items">The items to add to the collection.</param>
 33388    public void AddRange(IEnumerable<T> items) => IsReadOnly.IfFalse(() => _source.AddRange(items));
 389
 390    /// <summary>
 391    /// Removes multiple items from the collection if it is not read-only. This method checks the IsReadOnly property be
 392    /// </summary>
 393    /// <param name="itemsToRemove">The items to remove from the collection.</param>
 0394    public void RemoveMany(IEnumerable<T> itemsToRemove) => IsReadOnly.IfFalse(() => _source.RemoveMany(itemsToRemove));
 395
 396    /// <summary>
 397    /// Replaces the current items in the collection with the specified items if the collection is not read-only. This m
 398    /// </summary>
 399    /// <param name="items">The items to set in the collection.</param>
 0400    public void Set(IEnumerable<T> items) => IsReadOnly.IfFalse(() => _source.Edit(x =>
 0401    {
 0402        x.Clear();
 0403        x.AddRange(items);
 0404    }));
 405
 406    #endregion
 407
 408    #region Observable
 409
 410    /// <summary>
 411    /// Observes collection changes on the specified source collection and returns an observable sequence of collection 
 412    /// </summary>
 413    /// <param name="source">The source collection to observe for changes.</param>
 414    /// <returns>An observable sequence of collection changed event arguments.</returns>
 415    private static IObservable<NotifyCollectionChangedEventArgs> ObserveCollectionChanges(
 416        INotifyCollectionChanged source) =>
 186417        System.Reactive.Linq.Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEve
 186418                h => source.CollectionChanged += h,
 186419                h => source.CollectionChanged -= h)
 186420            .Select(x => x.EventArgs);
 421
 422    /// <summary>
 423    /// Synchronizes <see cref="SourceCount"/> with the underlying source.
 424    /// </summary>
 425    private void UpdateSourceCount() =>
 399426        SetProperty(ref _sourceCount, _source.Count, nameof(SourceCount));
 427
 428    /// <summary>
 429    /// Synchronizes <see cref="Count"/> with the filtered view.
 430    /// </summary>
 431    private void UpdateFilteredCount() =>
 444432        SetProperty(ref _count, _filteredItems.Count, nameof(Count));
 433
 434    /// <summary>
 435    /// Subscribes to property changes of an item in the collection if it implements INotifyPropertyChanged. This method
 436    /// </summary>
 437    /// <param name="item">The item to observe for property changes.</param>
 438    /// <returns>A disposable that can be used to unsubscribe from property change notifications.</returns>
 439    private IDisposable SubscribeToItemChanges(T item) =>
 25788440        item is not INotifyPropertyChanged npc
 25788441            ? Disposable.Empty
 25788442            : System.Reactive.Linq.Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
 25788443                    h => npc.PropertyChanged += h,
 25788444                    h => npc.PropertyChanged -= h)
 25788445                .Subscribe(e =>
 25788446                {
 25788447                    var prop = e.EventArgs.PropertyName;
 25788448                    if (prop is null) return;
 25788449
 25788450                    var affectsFilter = _filterPropertyUsage.ContainsKey(prop);
 25788451                    var affectsSort = _sortPropertyUsage.ContainsKey(prop);
 25788452
 25788453                    if (affectsFilter)
 25788454                        _filterEngine.Invalidate();
 25788455
 25788456                    if (affectsSort)
 25788457                        _sortEngine.Invalidate();
 25788458                });
 459
 460    #endregion
 461
 462    #region Dependencies
 463
 464    /// <summary>
 465    /// Rebuilds the filter dependencies based on the provided filter. This method extracts the properties used in the f
 466    /// </summary>
 467    /// <param name="filter">The filter for which to rebuild dependencies.</param>
 468    private void RebuildFilterDependencies(IFilter<T> filter)
 469    {
 42470        _filterPropertyUsage.Clear();
 471
 42472        var expr = filter.ProvideExpression();
 42473        var deps = _dependencyExtractor.ExtractFilter(expr);
 474
 114475        foreach (var d in deps)
 15476            _filterPropertyUsage[d] = 1;
 42477    }
 478
 479    /// <summary>
 480    /// Rebuilds the sort dependencies based on the provided sorting properties. This method extracts the properties use
 481    /// </summary>
 482    /// <param name="sorting">The sorting properties for which to rebuild dependencies.</param>
 483    private void RebuildSortDependencies(ISortingProperty<T>[] sorting)
 484    {
 21485        _sortPropertyUsage.Clear();
 486
 72487        foreach (var s in sorting)
 488        {
 15489            var deps = _dependencyExtractor.ExtractSort(s.ProvideExpression());
 490
 30491            foreach (var d in deps)
 0492                _sortPropertyUsage[d] = 1;
 493        }
 21494    }
 495
 496    #endregion
 497}
 498

Methods/Properties

.ctor(MyNet.Observable.Collections.Sources.SourceEngine`1<T>,System.Reactive.Concurrency.IScheduler)
get_FilteredItems()
get_Items()
get_Source()
get_SourceCount()
get_CurrentSort()
get_CurrentFilter()
ConnectFiltered()
Connect()
ConnectSource()
DisposeManagedResources()
get_CurrentGrouping()
ConnectGroups()
SetGrouping(MyNet.Observable.Collections.Grouping.IGroupingProperty`1<T>[])
ClearGrouping()
SetFilter(MyNet.Observable.Collections.Filters.IFilter`1<T>)
ClearFilter()
SetSorting(MyNet.Observable.Collections.Sorting.ISortingProperty`1<T>[])
ClearSorting()
SetPaging(System.Int32,System.Int32)
ClearPaging()
System.Collections.Specialized.INotifyCollectionChanged.add_CollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventHandler)
System.Collections.Specialized.INotifyCollectionChanged.remove_CollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventHandler)
HandleCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs)
get_Count()
get_Item(System.Int32)
Add(T)
Clear()
Remove(T)
IndexOf(T)
Contains(T)
CopyTo(T[],System.Int32)
GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
AddRange(System.Collections.Generic.IEnumerable`1<T>)
RemoveMany(System.Collections.Generic.IEnumerable`1<T>)
Set(System.Collections.Generic.IEnumerable`1<T>)
ObserveCollectionChanges(System.Collections.Specialized.INotifyCollectionChanged)
UpdateSourceCount()
UpdateFilteredCount()
SubscribeToItemChanges(T)
RebuildFilterDependencies(MyNet.Observable.Collections.Filters.IFilter`1<T>)
RebuildSortDependencies(MyNet.Observable.Collections.Sorting.ISortingProperty`1<T>[])