diff --git a/MvvmHelpers.Tests/MvvmHelpers.Tests.csproj b/MvvmHelpers.Tests/MvvmHelpers.Tests.csproj index eef8627..b5ede74 100644 --- a/MvvmHelpers.Tests/MvvmHelpers.Tests.csproj +++ b/MvvmHelpers.Tests/MvvmHelpers.Tests.csproj @@ -1,4 +1,4 @@ - + Debug @@ -46,4 +46,7 @@ MvvmHelpers + + + \ No newline at end of file diff --git a/MvvmHelpers.Tests/ObservableRangeTests.cs b/MvvmHelpers.Tests/ObservableRangeTests.cs index 119ad18..63b3f2b 100644 --- a/MvvmHelpers.Tests/ObservableRangeTests.cs +++ b/MvvmHelpers.Tests/ObservableRangeTests.cs @@ -33,10 +33,35 @@ public void GroupingTestCase() orderby person.LastName group person by person.SortName into personGroup select new Grouping(personGroup.Key, personGroup); - + grouped.AddRange(sorted); } + + [Test()] + public void RemoveRange_RemoveTest() + { + ObservableRangeCollection collection = new ObservableRangeCollection(); + int[] toAdd = new[] { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3 }; + int[] toRemove = new[] { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 0, 0 }; + collection.AddRange(toAdd); + collection.CollectionChanged += (s, e) => + { + if (e.Action != System.Collections.Specialized.NotifyCollectionChangedAction.Remove) + Assert.Fail("RemoveRange didn't use Remove like requested."); + if (e.OldItems == null) + Assert.Fail("OldItems should not be null."); + int[] expected = new int[] { 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9 }; + if (expected.Length != e.OldItems.Count) + Assert.Fail("Expected and actual OldItems don't match."); + for (int i = 0; i < expected.Length; i++) + { + if (expected[i] != (int)e.OldItems[i]) + Assert.Fail("Expected and actual OldItems don't match."); + } + }; + collection.RemoveRange(toRemove, System.Collections.Specialized.NotifyCollectionChangedAction.Remove); + } } } diff --git a/MvvmHelpers/ObservableRangeCollection.cs b/MvvmHelpers/ObservableRangeCollection.cs index 1c13d45..5932363 100644 --- a/MvvmHelpers/ObservableRangeCollection.cs +++ b/MvvmHelpers/ObservableRangeCollection.cs @@ -37,6 +37,8 @@ public ObservableRangeCollection(IEnumerable collection) /// public void AddRange(IEnumerable collection, NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Add) { + if (notificationMode != NotifyCollectionChangedAction.Add && notificationMode != NotifyCollectionChangedAction.Reset) + throw new ArgumentException("Mode must be either Add or Reset for AddRange.", "notificationMode"); if (collection == null) throw new ArgumentNullException("collection"); @@ -69,16 +71,40 @@ public void AddRange(IEnumerable collection, NotifyCollectionChangedAction no } /// - /// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T). + /// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T). NOTE: with notificationMode = Remove, removed items starting index is not set because items are not guaranteed to be consecutive. /// - public void RemoveRange(IEnumerable collection) + public void RemoveRange(IEnumerable collection, NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Reset) { + if (notificationMode != NotifyCollectionChangedAction.Remove && notificationMode != NotifyCollectionChangedAction.Reset) + throw new ArgumentException("Mode must be either Remove or Reset for RemoveRange.", "notificationMode"); if (collection == null) throw new ArgumentNullException("collection"); - foreach (var i in collection) - Items.Remove(i); - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + CheckReentrancy(); + + if (notificationMode == NotifyCollectionChangedAction.Reset) + { + + foreach (var i in collection) + Items.Remove(i); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + + return; + } + + var changedItems = collection is List ? (List)collection : new List(collection); + for (int i = 0; i < changedItems.Count; i++) + { + if (!Items.Remove(changedItems[i])) + { + changedItems.RemoveAt(i); //Can't use a foreach because changedItems is intended to be (carefully) modified + i--; + } + } + + OnPropertyChanged(new PropertyChangedEventArgs("Count")); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, changedItems, -1)); } ///