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

Commit 3cfd951

Browse files
committed
Update
1 parent 667a7e6 commit 3cfd951

File tree

2 files changed

+54
-43
lines changed

2 files changed

+54
-43
lines changed

WpfObservableRangeCollection/ObservableRangeCollection.cs

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
namespace CodingNinja.Wpf.ObjectModel;
1010

1111
/// <summary>
12-
/// <see cref="ObservableCollection{T}"/> that supports bulk operations to avoid frequent update notification events.
12+
/// An <see cref="ObservableCollection{T}"/> that supports bulk operations to avoid frequent update notification events.
1313
/// </summary>
1414
/// <typeparam name="T"></typeparam>
1515
public class ObservableRangeCollection<T> : ObservableCollection<T>
@@ -48,14 +48,14 @@ public ObservableRangeCollection(bool allowDuplicates = true, EqualityComparer<T
4848

4949
/// <summary>
5050
/// Initializes a new instance of the <see cref="ObservableRangeCollection{T}"/> class that contains
51-
/// elements copied from the specified collection and has sufficient capacity
52-
/// to accommodate the number of elements copied.
51+
/// items copied from the specified collection and has sufficient capacity
52+
/// to accommodate the number of items copied.
5353
/// </summary>
54-
/// <param name="collection">The collection whose elements are copied to the new list.</param>
54+
/// <param name="collection">The collection whose items are copied to the new list.</param>
5555
/// <param name="allowDuplicates">Whether duplicate items are allowed in the collection.</param>
5656
/// <param name="comparer">Supports for <see cref="AllowDuplicates"/>.</param>
5757
/// <remarks>
58-
/// The elements are copied onto the <see cref="ObservableRangeCollection{T}"/> in the
58+
/// The items are copied onto the <see cref="ObservableRangeCollection{T}"/> in the
5959
/// same order they are read by the enumerator of the collection.
6060
/// </remarks>
6161
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is a null reference.</exception>
@@ -67,13 +67,13 @@ public ObservableRangeCollection(IEnumerable<T> collection, bool allowDuplicates
6767

6868
/// <summary>
6969
/// Initializes a new instance of the <see cref="ObservableRangeCollection{T}"/> class
70-
/// that contains elements copied from the specified list.
70+
/// that contains items copied from the specified list.
7171
/// </summary>
72-
/// <param name="list">The list whose elements are copied to the new list.</param>
72+
/// <param name="list">The list whose items are copied to the new list.</param>
7373
/// <param name="allowDuplicates">Whether duplicate items are allowed in the collection.</param>
7474
/// <param name="comparer">Supports for <see cref="AllowDuplicates"/>.</param>
7575
/// <remarks>
76-
/// The elements are copied onto the <see cref="ObservableRangeCollection{T}"/> in the
76+
/// The items are copied onto the <see cref="ObservableRangeCollection{T}"/> in the
7777
/// same order they are read by the enumerator of the list.
7878
/// </remarks>
7979
/// <exception cref="ArgumentNullException"><paramref name="list"/> is a null reference.</exception>
@@ -98,11 +98,13 @@ public ObservableRangeCollection(List<T> list, bool allowDuplicates = true, Equa
9898
/// disallowing duplicate items, based on <see cref="Comparer"/>.
9999
/// This might indeed consume background performance, but in the other hand,
100100
/// it will pay off in UI performance as less required UI updates are required.
101+
/// Default value: <see langword="true"/>.
101102
/// </summary>
102103
public bool AllowDuplicates { get; set; } = true;
103104

104105
/// <summary>
105106
/// Supports for <see cref="AllowDuplicates"/>.
107+
/// Default value: <see cref="EqualityComparer{T}.Default"/>.
106108
/// </summary>
107109
public EqualityComparer<T> Comparer { get; }
108110

@@ -117,28 +119,28 @@ public ObservableRangeCollection(List<T> list, bool allowDuplicates = true, Equa
117119
#region Public Methods
118120

119121
/// <summary>
120-
/// Adds the elements of the specified collection to the end of the <see cref="ObservableCollection{T}"/>.
122+
/// Adds the items of the specified collection to the end of this <see cref="ObservableCollection{T}"/>.
121123
/// </summary>
122124
/// <param name="collection">
123-
/// The collection whose elements should be added to the end of the <see cref="ObservableCollection{T}"/>.
124-
/// The collection itself cannot be null, but it can contain elements that are null, if type T is a reference type.
125+
/// The collection whose items should be added to the end of this <see cref="ObservableCollection{T}"/>.
126+
/// The collection itself cannot be null, but it can contain items that are null, if type T is a reference type.
125127
/// </param>
126-
/// <returns>Returns the number of items successfully added.</returns>
128+
/// <returns>Returns the number of items successfully added, its related to <see cref="AllowDuplicates"/>.</returns>
127129
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is null.</exception>
128130
public int AddRange(IEnumerable<T> collection)
129131
{
130132
return InsertRange(Count, collection);
131133
}
132134

133135
/// <summary>
134-
/// Inserts the elements of a collection into the <see cref="ObservableCollection{T}"/> at the specified index.
136+
/// Inserts the items of a collection into this <see cref="ObservableCollection{T}"/> at the specified index.
135137
/// </summary>
136-
/// <param name="index">The zero-based index at which the new elements should be inserted.</param>
138+
/// <param name="index">The zero-based index at which the new items should be inserted.</param>
137139
/// <param name="collection">
138-
/// The collection whose elements should be inserted into the <see cref="List{T}"/>.
139-
/// The collection itself cannot be null, but it can contain elements that are null, if type T is a reference type.
140+
/// The collection whose items should be inserted into the <see cref="List{T}"/>.
141+
/// The collection itself cannot be null, but it can contain items that are null, if type T is a reference type.
140142
/// </param>
141-
/// <returns>Returns the number of items successfully inserted.</returns>
143+
/// <returns>Returns the number of items successfully inserted, its related to <see cref="AllowDuplicates"/>.</returns>
142144
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is null.</exception>
143145
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is not in the collection range.</exception>
144146
public int InsertRange(int index, IEnumerable<T> collection)
@@ -184,7 +186,7 @@ public int InsertRange(int index, IEnumerable<T> collection)
184186

185187
OnEssentialPropertiesChanged();
186188

187-
// changedItems cannot be IEnumerable(lazy type).
189+
// changedItems cannot be IEnumerable(lazy evaluation).
188190
var changedItems = collection.ToList();
189191
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, changedItems, index));
190192

@@ -195,7 +197,7 @@ public int InsertRange(int index, IEnumerable<T> collection)
195197
/// Iterates over the collection and removes all items that satisfy the specified match.
196198
/// </summary>
197199
/// <remarks>The complexity is O(n).</remarks>
198-
/// <param name="match">A function to test each element for a condition.</param>
200+
/// <param name="match">A function to test each item for a condition.</param>
199201
/// <returns>Returns the number of items successfully removed.</returns>
200202
/// <exception cref="ArgumentNullException"><paramref name="match"/> is null.</exception>
201203
public int RemoveAll(Predicate<T> match)
@@ -205,15 +207,16 @@ public int RemoveAll(Predicate<T> match)
205207

206208
/// <summary>
207209
/// Iterates over the specified range within the collection and removes all items that satisfy the specified match.
208-
/// <para>NOTE: Consecutively matching elements will trigger the <see cref="ObservableCollection{T}.CollectionChanged"/> event at once.</para>
210+
/// <para>NOTE: Consecutively matching items will trigger the <see cref="ObservableCollection{T}.CollectionChanged"/> event at once.</para>
209211
/// </summary>
210212
/// <remarks>The complexity is O(n).</remarks>
211213
/// <param name="index">The index of where to start performing the search.</param>
212214
/// <param name="count">The number of items to iterate on.</param>
213-
/// <param name="match">A function to test each element for a condition.</param>
215+
/// <param name="match">A function to test each item for a condition.</param>
214216
/// <returns>Returns the number of items successfully removed.</returns>
215217
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
216218
/// <exception cref="ArgumentOutOfRangeException"><paramref name="count"/> is out of range.</exception>
219+
/// <exception cref="ArgumentException"/>
217220
/// <exception cref="ArgumentNullException"><paramref name="match"/> is null.</exception>
218221
public int RemoveAll(int index, int count, Predicate<T> match)
219222
{
@@ -227,9 +230,9 @@ public int RemoveAll(int index, int count, Predicate<T> match)
227230
throw new ArgumentOutOfRangeException(nameof(count));
228231
}
229232

230-
if (index + count > Count)
233+
if (Count - index < count)
231234
{
232-
throw new ArgumentException($"{nameof(index)} + {nameof(count)} must be less than or equal to the ObservableCollection.Count.");
235+
throw new ArgumentException("Offset and length were out of bounds for the array or count is greater than the number of items from index to the end of the source collection.");
233236
}
234237

235238
ArgumentNullException.ThrowIfNull(match);
@@ -292,7 +295,7 @@ public int RemoveAll(int index, int count, Predicate<T> match)
292295
}
293296

294297
/// <summary>
295-
/// Removes the first occurence of each item in the specified collection from the <see cref="ObservableCollection{T}"/>.
298+
/// Removes the first occurence of each item in the specified collection from this <see cref="ObservableCollection{T}"/>.
296299
/// <para>NOTE: Removed items starting index is not set because items are not guaranteed to be consecutive.</para>
297300
/// </summary>
298301
/// <param name="collection">The items to remove.</param>
@@ -344,19 +347,20 @@ public int RemoveRange(IEnumerable<T> collection)
344347
}
345348
else
346349
{
347-
// changedItems cannot be IEnumerable(lazy type).
350+
// changedItems cannot be IEnumerable(lazy evaluation).
348351
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, collection.ToList()));
349352
}
350353

351354
return removedCount;
352355
}
353356

354357
/// <summary>
355-
/// Removes a range of elements from the <see cref="ObservableCollection{T}"/>.
358+
/// Removes a range of items from this <see cref="ObservableCollection{T}"/>.
356359
/// </summary>
357-
/// <param name="index">The zero-based starting index of the range of elements to remove.</param>
358-
/// <param name="count">The number of elements to remove.</param>
360+
/// <param name="index">The zero-based starting index of the range of items to remove.</param>
361+
/// <param name="count">The number of items to remove.</param>
359362
/// <exception cref="ArgumentOutOfRangeException">The specified range is exceeding the collection.</exception>
363+
/// <exception cref="ArgumentException"/>
360364
public void RemoveRange(int index, int count)
361365
{
362366
if (index < 0)
@@ -369,9 +373,9 @@ public void RemoveRange(int index, int count)
369373
throw new ArgumentOutOfRangeException(nameof(count));
370374
}
371375

372-
if (index + count > Count)
376+
if (Count - index < count)
373377
{
374-
throw new ArgumentException($"{nameof(index)} + {nameof(count)} must be less than or equal to the ObservableCollection.Count.");
378+
throw new ArgumentException("Offset and length were out of bounds for the array or count is greater than the number of items from index to the end of the source collection.");
375379
}
376380

377381
if (count == 0)
@@ -410,34 +414,37 @@ public void RemoveRange(int index, int count)
410414
/// Clears the current collection and replaces it with the specified item, using <see cref="Comparer"/>.
411415
/// </summary>
412416
/// <param name="item">The item to fill the collection with, after clearing it.</param>
413-
public void Replace(T item)
417+
/// <returns>Returns the amount of change in the number of current collection.</returns>
418+
public int Replace(T item)
414419
{
415-
ReplaceRange(0, Count, new[] { item });
420+
return ReplaceRange(0, Count, new[] { item });
416421
}
417422

418423
/// <summary>
419424
/// Clears the current collection and replaces it with the specified collection, using <see cref="Comparer"/>.
420425
/// </summary>
421426
/// <param name="collection">The items to fill the collection with, after clearing it.</param>
427+
/// <returns>Returns the amount of change in the number of current collection.</returns>
422428
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is null.</exception>
423-
public void ReplaceRange(IEnumerable<T> collection)
429+
public int ReplaceRange(IEnumerable<T> collection)
424430
{
425-
ReplaceRange(0, Count, collection);
431+
return ReplaceRange(0, Count, collection);
426432
}
427433

428434
/// <summary>
429435
/// Removes the specified range and inserts the specified collection in its position, leaving equal items in equal positions intact.
430-
/// <para>When index and count are equal to 0, it is equivalent to InsertRange(0, collection).</para>
436+
/// <para>When both index and count are equal to 0, it is equivalent to InsertRange(0, collection).</para>
431437
/// </summary>
432438
/// <remarks>This method is roughly equivalent to <see cref="RemoveRange(Int32, Int32)"/> then <see cref="InsertRange(Int32, IEnumerable{T})"/>.</remarks>
433439
/// <param name="index">The index of where to start the replacement.</param>
434440
/// <param name="count">The number of items to be replaced.</param>
435441
/// <param name="collection">The collection to insert in that location.</param>
442+
/// <returns>Returns the amount of change in the number of current collection.</returns>
436443
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
437444
/// <exception cref="ArgumentOutOfRangeException"><paramref name="count"/> is out of range.</exception>
445+
/// <exception cref="ArgumentException"/>
438446
/// <exception cref="ArgumentNullException"><paramref name="collection"/> is null.</exception>
439-
/// <exception cref="ArgumentNullException"><see cref="Comparer"/> is null.</exception>
440-
public void ReplaceRange(int index, int count, IEnumerable<T> collection)
447+
public int ReplaceRange(int index, int count, IEnumerable<T> collection)
441448
{
442449
void OnRangeReplaced(int followingItemIndex, ICollection<T> newCluster, ICollection<T> oldCluster)
443450
{
@@ -469,9 +476,9 @@ void OnRangeReplaced(int followingItemIndex, ICollection<T> newCluster, ICollect
469476
throw new ArgumentOutOfRangeException(nameof(count));
470477
}
471478

472-
if (index + count > Count)
479+
if (Count - index < count)
473480
{
474-
throw new ArgumentException($"{nameof(index)} + {nameof(count)} must be less than or equal to the ObservableCollection.Count.");
481+
throw new ArgumentException("Offset and length were out of bounds for the array or count is greater than the number of items from index to the end of the source collection.");
475482
}
476483

477484
ArgumentNullException.ThrowIfNull(collection);
@@ -480,7 +487,7 @@ void OnRangeReplaced(int followingItemIndex, ICollection<T> newCluster, ICollect
480487
{
481488
RemoveRange(index, count);
482489

483-
return;
490+
return -count;
484491
}
485492

486493
if (!AllowDuplicates)
@@ -492,11 +499,13 @@ void OnRangeReplaced(int followingItemIndex, ICollection<T> newCluster, ICollect
492499

493500
if (index + count == 0)
494501
{
495-
InsertRange(0, collection);
502+
int added = InsertRange(0, collection);
496503

497-
return;
504+
return added;
498505
}
499506

507+
int oldCount = Count;
508+
500509
if (collection is not IList<T> list)
501510
{
502511
list = new List<T>(collection);
@@ -584,6 +593,8 @@ void OnRangeReplaced(int followingItemIndex, ICollection<T> newCluster, ICollect
584593
OnIndexerPropertyChanged();
585594
}
586595
}
596+
597+
return Count - oldCount;
587598
}
588599

589600
#endregion Public Methods

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.1.0</Version>
17+
<Version>2.2.0</Version>
1818
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
1919
</PropertyGroup>
2020

0 commit comments

Comments
 (0)