Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Added Range Manipulation APIs to Collection<T> and ObservableCollection<T> #35772

Merged
merged 19 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f4f0d52
Added Collection<T> AddRange and InsertRange and added new XUnit test…
Mar 4, 2019
17e62ef
Removed redudent AsSpan parameter in test code
Apr 22, 2019
5e453ad
Removed stale code in test code
Apr 22, 2019
512c517
Removed redundent Assert.NotNull calls in several tests
Apr 22, 2019
f4968c9
Added additional check in InsertRange to verify the input collection.…
Apr 22, 2019
a50f567
Removed stale code from the `NonNullObservableCollection<T>` test har…
Apr 22, 2019
781612b
Removed unnecessary whitespace
Apr 23, 2019
afb8909
Renamed new API tests to include the .netcoreapp extension; Updated .…
Apr 24, 2019
eb1d802
Renamed CollectionTests -> CollectionTests.netcoreapp.cs and only run…
Apr 24, 2019
6403a78
Added UAP and UAPAOT build configurations for System.ObjectModel tests
Apr 24, 2019
9ee2e12
Updated ObservableCollection/Collection tests that use new APIs to be…
Apr 24, 2019
d948ef5
Added CollectionTestBase as parent class for CollectionTests for the …
Apr 24, 2019
8b527af
Adding using statements back in which were failing the build
Apr 24, 2019
fa550f4
Moving private classes from the netcoreapp tests to the regular Colle…
Apr 24, 2019
d36ec1e
Added missing using statement for colleciton tests
Apr 24, 2019
e019416
Added if-block that certifies we have replaced items before raising t…
May 2, 2019
01b9496
Removed whitespace in System.Runtime.Tests.csproj
May 2, 2019
33bcaa0
Added negative test case for ReplaceRange when no items are replaced
May 2, 2019
bbf807c
Fixed issue with failing test
May 2, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged,
[NonSerialized]
private int _blockReentrancyCount;

[NonSerialized]
private bool _skipRaisingEvents;

/// <summary>
/// Initializes a new instance of ObservableCollection that is empty and has default initial capacity.
/// </summary>
Expand Down Expand Up @@ -121,9 +124,95 @@ protected override void RemoveItem(int index)

base.RemoveItem(index);

OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
if (!_skipRaisingEvents)
SkyeHoefling marked this conversation as resolved.
Show resolved Hide resolved
{
OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
}
}

/// <summary>
/// Called by base class Collection&lt;T&gt; when a count of items is removed from the list;
/// raises a CollectionChanged event to any listeners.
/// </summary>
protected override void RemoveItemsRange(int index, int count)
SkyeHoefling marked this conversation as resolved.
Show resolved Hide resolved
{
CheckReentrancy();

T[] removedItems = null;

bool ignore = _skipRaisingEvents;
if (!ignore)
{
_skipRaisingEvents = true;

if (count > 0)
{
removedItems = new T[count];
for (int i = 0; i < count; i++)
{
removedItems[i] = this[index + i];
}
}
}

try
{
base.RemoveItemsRange(index, count);
}
finally
{
if (!ignore)
{
_skipRaisingEvents = false;
}
}

if (count > 0 && !_skipRaisingEvents)
{
OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItems, index);
SkyeHoefling marked this conversation as resolved.
Show resolved Hide resolved
}
}

/// <summary>
/// Called by base class Collection&lt;T&gt; when a collection of items is added to list;
/// raises a CollectionChanged event to any listeners.
/// </summary>
protected override void ReplaceItemsRange(int index, int count, IEnumerable<T> collection)
{
CheckReentrancy();

_skipRaisingEvents = true;

T[] itemsToReplace = new T[count - index];
for (int i = index; i < count; i++)
{
itemsToReplace[i] = this[i];
}

try
{
base.ReplaceItemsRange(index, count, collection);
}
finally
{
_skipRaisingEvents = false;
}

if (!_skipRaisingEvents)
{
IList newItems = collection is IList list ? list : new List<T>(collection);

if (newItems.Count > 0)
{
OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Replace, itemsToReplace, newItems, index);
}
}
}

/// <summary>
Expand All @@ -135,9 +224,51 @@ protected override void InsertItem(int index, T item)
CheckReentrancy();
base.InsertItem(index, item);

OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
if (!_skipRaisingEvents)
{
OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
}

/// <summary>
/// Called by base class Collection&lt;T&gt; when a collection of items is added to list;
/// raises a CollectionChanged event to any listeners.
/// </summary>
protected override void InsertItemsRange(int index, IEnumerable<T> collection)
{
CheckReentrancy();

bool ignore = _skipRaisingEvents;
if (!ignore)
{
_skipRaisingEvents = true;
}

try
{
base.InsertItemsRange(index, collection);
}
finally
{
if (!ignore)
{
_skipRaisingEvents = false;
}
}

if (!_skipRaisingEvents)
SkyeHoefling marked this conversation as resolved.
Show resolved Hide resolved
{
IList newItems = collection is IList list ? list : new List<T>(collection);

if (newItems.Count > 0)
{
OnCountPropertyChanged();
OnIndexerPropertyChanged();
OnCollectionChanged(NotifyCollectionChangedAction.Add, newItems, index);
}
}
}

/// <summary>
Expand Down Expand Up @@ -265,6 +396,14 @@ private void OnCollectionChanged(NotifyCollectionChangedAction action, object it
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
}

/// <summary>
/// Helper to raise CollectionChanged event to any listeners
/// </summary>
private void OnCollectionChanged(NotifyCollectionChangedAction action, IList items, int index)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, items, index));
}

/// <summary>
/// Helper to raise CollectionChanged event to any listeners
/// </summary>
Expand All @@ -281,6 +420,14 @@ private void OnCollectionChanged(NotifyCollectionChangedAction action, object ol
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
}

/// <summary>
/// Helper to raise CollectionChanged event to any listeners
/// </summary>
private void OnCollectionChanged(NotifyCollectionChangedAction action, IList oldItems, IList newItems, int index)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItems, oldItems, index));
}

/// <summary>
/// Helper to raise CollectionChanged event with action == Reset to any listeners
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/System.ObjectModel/tests/Configurations.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<BuildConfigurations>
netstandard;
netcoreapp;
uap;
uapaot;
</BuildConfigurations>
</PropertyGroup>
</Project>
Loading