Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 16943df

Browse files
committed
Update
1 parent c60d4c5 commit 16943df

File tree

3 files changed

+50
-50
lines changed

3 files changed

+50
-50
lines changed

WpfObservableRangeCollection/ObservableRangeCollection.cs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -39,35 +39,50 @@ public class ObservableRangeCollection<T> : ObservableCollection<T>
3939
/// <summary>
4040
/// Initializes a new instance of <see cref="ObservableCollection{T}"/> that is empty and has default initial capacity.
4141
/// </summary>
42-
public ObservableRangeCollection()
43-
{ }
42+
/// <param name="allowDuplicates">Whether duplicate items are allowed in the collection.</param>
43+
/// <param name="comparer">Support for <see cref="AllowDuplicates"/>.</param>
44+
public ObservableRangeCollection(bool allowDuplicates = true, EqualityComparer<T>? comparer = null)
45+
{
46+
AllowDuplicates = allowDuplicates;
47+
Comparer = comparer ?? EqualityComparer<T>.Default;
48+
}
4449

4550
/// <summary>
46-
/// Initializes a new instance of the ObservableCollection class that contains
51+
/// Initializes a new instance of the <see cref="ObservableCollection{T}"/> class that contains
4752
/// elements copied from the specified collection and has sufficient capacity
4853
/// to accommodate the number of elements copied.
4954
/// </summary>
5055
/// <param name="collection">The collection whose elements are copied to the new list.</param>
56+
/// <param name="allowDuplicates">Whether duplicate items are allowed in the collection.</param>
57+
/// <param name="comparer">Support for <see cref="AllowDuplicates"/>.</param>
5158
/// <remarks>
52-
/// The elements are copied onto the ObservableCollection in the
59+
/// The elements are copied onto the <see cref="ObservableCollection{T}"/> in the
5360
/// same order they are read by the enumerator of the collection.
5461
/// </remarks>
5562
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is a null reference.</exception>
56-
public ObservableRangeCollection(IEnumerable<T> collection) : base(collection)
57-
{ }
63+
public ObservableRangeCollection(IEnumerable<T> collection, bool allowDuplicates = true, EqualityComparer<T>? comparer = null) : base(collection)
64+
{
65+
AllowDuplicates = allowDuplicates;
66+
Comparer = comparer ?? EqualityComparer<T>.Default;
67+
}
5868

5969
/// <summary>
60-
/// Initializes a new instance of the ObservableCollection class
70+
/// Initializes a new instance of the <see cref="ObservableCollection{T}"/> class
6171
/// that contains elements copied from the specified list.
6272
/// </summary>
6373
/// <param name="list">The list whose elements are copied to the new list.</param>
74+
/// <param name="allowDuplicates">Whether duplicate items are allowed in the collection.</param>
75+
/// <param name="comparer">Support for <see cref="AllowDuplicates"/>.</param>
6476
/// <remarks>
65-
/// The elements are copied onto the ObservableCollection in the
77+
/// The elements are copied onto the <see cref="ObservableCollection{T}"/> in the
6678
/// same order they are read by the enumerator of the list.
6779
/// </remarks>
6880
/// <exception cref="ArgumentNullException"><paramref name="list"/> is a null reference.</exception>
69-
public ObservableRangeCollection(List<T> list) : base(list)
70-
{ }
81+
public ObservableRangeCollection(List<T> list, bool allowDuplicates = true, EqualityComparer<T>? comparer = null) : base(list)
82+
{
83+
AllowDuplicates = allowDuplicates;
84+
Comparer = comparer ?? EqualityComparer<T>.Default;
85+
}
7186

7287
#endregion Constructors
7388

@@ -79,8 +94,6 @@ public ObservableRangeCollection(List<T> list) : base(list)
7994

8095
#region Public Properties
8196

82-
private EqualityComparer<T>? _comparer;
83-
8497
/// <summary>
8598
/// Gets or sets a value indicating whether this collection acts as a <see cref="HashSet{T}"/>,
8699
/// disallowing duplicate items, based on <see cref="Comparer"/>.
@@ -92,11 +105,7 @@ public ObservableRangeCollection(List<T> list) : base(list)
92105
/// <summary>
93106
/// Support for <see cref="AllowDuplicates"/>.
94107
/// </summary>
95-
public EqualityComparer<T> Comparer
96-
{
97-
get => _comparer ??= EqualityComparer<T>.Default;
98-
private set => _comparer = value;
99-
}
108+
public EqualityComparer<T> Comparer { get; }
100109

101110
#endregion Public Properties
102111

@@ -182,7 +191,7 @@ public void InsertRange(int index, IEnumerable<T> collection)
182191
/// Iterates over the collection and removes all items that satisfy the specified match.
183192
/// </summary>
184193
/// <remarks>The complexity is O(n).</remarks>
185-
/// <param name="match"></param>
194+
/// <param name="match">Match the item to be removed</param>
186195
/// <returns>Returns the number of elements that where </returns>
187196
/// <exception cref="ArgumentNullException"><paramref name="match"/> is null.</exception>
188197
public int RemoveAll(Predicate<T> match)
@@ -192,11 +201,12 @@ public int RemoveAll(Predicate<T> match)
192201

193202
/// <summary>
194203
/// Iterates over the specified range within the collection and removes all items that satisfy the specified match.
204+
/// <para>NOTE: Consecutively matching elements will trigger the <see cref="ObservableCollection{T}.CollectionChanged"/> event at once.</para>
195205
/// </summary>
196206
/// <remarks>The complexity is O(n).</remarks>
197207
/// <param name="index">The index of where to start performing the search.</param>
198208
/// <param name="count">The number of items to iterate on.</param>
199-
/// <param name="match"></param>
209+
/// <param name="match">Match the item to be removed.</param>
200210
/// <returns>Returns the number of elements that where.</returns>
201211
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
202212
/// <exception cref="ArgumentOutOfRangeException"><paramref name="count"/> is out of range.</exception>
@@ -279,6 +289,7 @@ public int RemoveAll(int index, int count, Predicate<T> match)
279289

280290
/// <summary>
281291
/// Removes the first occurence of each item in the specified collection from the <see cref="ObservableCollection{T}"/>.
292+
/// <para>NOTE: Removed items starting index is not set because items are not guaranteed to be consecutive.</para>
282293
/// </summary>
283294
/// <param name="collection">The items to remove.</param>
284295
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is null.</exception>
@@ -307,29 +318,16 @@ public void RemoveRange(IEnumerable<T> collection)
307318

308319
CheckReentrancy();
309320

310-
var clusters = new Dictionary<int, List<T>>();
311-
int lastIndex = -1;
312-
List<T>? lastCluster = null;
321+
bool raiseEvents = false;
313322

314323
foreach (var item in collection)
315324
{
316-
int index = IndexOf(item);
317-
318-
if (index < 0)
319-
{
320-
continue;
321-
}
322-
323-
Items.RemoveAt(index);
325+
raiseEvents |= Items.Remove(item);
326+
}
324327

325-
if (lastIndex == index && lastCluster is not null)
326-
{
327-
lastCluster.Add(item);
328-
}
329-
else
330-
{
331-
clusters[lastIndex = index] = lastCluster = new List<T> { item };
332-
}
328+
if (!raiseEvents)
329+
{
330+
return;
333331
}
334332

335333
OnEssentialPropertiesChanged();
@@ -376,6 +374,7 @@ public void RemoveRange(int index, int count)
376374
if (count == 1)
377375
{
378376
RemoveItem(index);
377+
379378
return;
380379
}
381380

@@ -400,8 +399,7 @@ public void RemoveRange(int index, int count)
400399
}
401400

402401
/// <summary>
403-
/// Clears the current collection and replaces it with the specified item,
404-
/// using <see cref="Comparer"/>.
402+
/// Clears the current collection and replaces it with the specified item, using <see cref="Comparer"/>.
405403
/// </summary>
406404
/// <param name="item">The item to fill the collection with, after clearing it.</param>
407405
public void Replace(T item)
@@ -410,8 +408,7 @@ public void Replace(T item)
410408
}
411409

412410
/// <summary>
413-
/// Clears the current collection and replaces it with the specified collection,
414-
/// using <see cref="Comparer"/>.
411+
/// Clears the current collection and replaces it with the specified collection, using <see cref="Comparer"/>.
415412
/// </summary>
416413
/// <param name="collection">The items to fill the collection with, after clearing it.</param>
417414
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is null.</exception>
@@ -681,15 +678,15 @@ protected override void SetItem(int index, T item)
681678
#region Private Methods
682679

683680
/// <summary>
684-
/// Helper to raise CollectionChanged event to any listeners
681+
/// Helper to raise CollectionChanged event to any listeners.
685682
/// </summary>
686683
private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index)
687684
{
688685
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
689686
}
690687

691688
/// <summary>
692-
/// Helper to raise CollectionChanged event with action == Reset to any listeners
689+
/// Helper to raise CollectionChanged event with action == Reset to any listeners.
693690
/// </summary>
694691
private void OnCollectionReset()
695692
{
@@ -706,8 +703,8 @@ private void OnEssentialPropertiesChanged()
706703
}
707704

708705
/// <summary>
709-
/// /// Helper to raise a PropertyChanged event for the Indexer property
710-
/// /// </summary>
706+
/// Helper to raise a PropertyChanged event for the Indexer property.
707+
/// </summary>
711708
private void OnIndexerPropertyChanged()
712709
{
713710
OnPropertyChanged(EventArgsCache.IndexerPropertyChanged);

WpfObservableRangeCollection/WpfObservableRangeCollection.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,22 @@ public void Dispose()
6161
/// <summary>
6262
/// <inheritdoc/>
6363
/// </summary>
64-
public WpfObservableRangeCollection() : base()
64+
public WpfObservableRangeCollection(bool allowDuplicates = true, EqualityComparer<T>? comparer = null)
65+
: base(allowDuplicates, comparer)
6566
{ }
6667

6768
/// <summary>
6869
/// <inheritdoc/>
6970
/// </summary>
70-
public WpfObservableRangeCollection(IEnumerable<T> collection) : base(collection)
71+
public WpfObservableRangeCollection(IEnumerable<T> collection, bool allowDuplicates = true, EqualityComparer<T>? comparer = null)
72+
: base(collection, allowDuplicates, comparer)
7173
{ }
7274

7375
/// <summary>
7476
/// <inheritdoc/>
7577
/// </summary>
76-
public WpfObservableRangeCollection(List<T> list) : base(list)
78+
public WpfObservableRangeCollection(List<T> list, bool allowDuplicates = true, EqualityComparer<T>? comparer = null)
79+
: base(list, allowDuplicates, comparer)
7780
{ }
7881

7982
/// <summary>

WpfObservableRangeCollection/WpfObservableRangeCollection.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<Title>$(AssemblyName)</Title>
1515
<PackageTags>WpfObservableRangeCollection;ObservableRangeCollection;ObservableCollection;CollectionView;Wpf</PackageTags>
1616
<PackageReadmeFile>README.md</PackageReadmeFile>
17-
<Version>2.0.0</Version>
17+
<Version>2.0.1</Version>
1818
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
1919
</PropertyGroup>
2020

0 commit comments

Comments
 (0)