diff --git a/Nuclex.Support (net-4.0).csproj b/Nuclex.Support (net-4.0).csproj
index 98e931f..7057908 100644
--- a/Nuclex.Support (net-4.0).csproj
+++ b/Nuclex.Support (net-4.0).csproj
@@ -85,6 +85,10 @@
SerializationCloner.cs
+
+
+ Constants.cs
+
Deque.cs
diff --git a/Nuclex.Support (xna-4.0-phone7).csproj b/Nuclex.Support (xna-4.0-phone7).csproj
index 26cbdf0..67cf800 100644
--- a/Nuclex.Support (xna-4.0-phone7).csproj
+++ b/Nuclex.Support (xna-4.0-phone7).csproj
@@ -116,6 +116,10 @@
SerializationCloner.cs
+
+
+ Constants.cs
+
Deque.cs
diff --git a/Nuclex.Support (xna-4.0-xbox360).csproj b/Nuclex.Support (xna-4.0-xbox360).csproj
index 4eafe45..aa75ddc 100644
--- a/Nuclex.Support (xna-4.0-xbox360).csproj
+++ b/Nuclex.Support (xna-4.0-xbox360).csproj
@@ -127,6 +127,10 @@
SerializationCloner.cs
+
+
+ Constants.cs
+
Deque.cs
diff --git a/Source/Collections/Constants.Test.cs b/Source/Collections/Constants.Test.cs
new file mode 100644
index 0000000..e8bdbc5
--- /dev/null
+++ b/Source/Collections/Constants.Test.cs
@@ -0,0 +1,49 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2012 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.Collections.Specialized;
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Collections {
+
+ /// Unit Test for the collection constants
+ [TestFixture]
+ internal class ConstantsTest {
+
+ ///
+ /// Verifies that the collection reset event arguments have 'reset' specified as
+ /// their action
+ ///
+ [Test]
+ public void CollectionResetEventArgsHaveResetActionSet() {
+ Assert.AreEqual(
+ NotifyCollectionChangedAction.Reset, Constants.NotifyCollectionResetEventArgs.Action
+ );
+ }
+
+ }
+
+} // namespace Nuclex.Support.Collections
+
+#endif // UNITTEST
diff --git a/Source/Collections/Constants.cs b/Source/Collections/Constants.cs
new file mode 100644
index 0000000..202a3ff
--- /dev/null
+++ b/Source/Collections/Constants.cs
@@ -0,0 +1,35 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2012 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Specialized;
+
+namespace Nuclex.Support.Collections {
+
+ /// Contains fixed constants used by some collections
+ public static class Constants {
+
+ /// Fixed event args used to notify that the collection has reset
+ public static readonly NotifyCollectionChangedEventArgs NotifyCollectionResetEventArgs =
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
+
+ }
+
+} // namespace Nuclex.Support.Collections
diff --git a/Source/Collections/IObservableCollection.cs b/Source/Collections/IObservableCollection.cs
index d932511..48239e7 100644
--- a/Source/Collections/IObservableCollection.cs
+++ b/Source/Collections/IObservableCollection.cs
@@ -34,10 +34,8 @@ namespace Nuclex.Support.Collections {
/// Raised when an item is removed from the collection
event EventHandler> ItemRemoved;
-#if false
/// Raised when an item is replaced in the collection
- event EventHandler> ItemReplaced;
-#endif
+ event EventHandler> ItemReplaced;
/// Raised when the collection is about to be cleared
///
diff --git a/Source/Collections/ObservableCollection.cs b/Source/Collections/ObservableCollection.cs
index fc65d06..037129e 100644
--- a/Source/Collections/ObservableCollection.cs
+++ b/Source/Collections/ObservableCollection.cs
@@ -34,14 +34,19 @@ namespace Nuclex.Support.Collections {
ICollection,
ICollection,
#if !NO_SPECIALIZED_COLLECTIONS
- INotifyCollectionChanged,
+ INotifyCollectionChanged,
#endif
- IObservableCollection {
+ IObservableCollection {
/// Raised when an item has been added to the collection
public event EventHandler> ItemAdded;
/// Raised when an item is removed from the collection
public event EventHandler> ItemRemoved;
+ /// Raised when an item is replaced in the collection
+ public event EventHandler> ItemReplaced {
+ add { }
+ remove { }
+ }
/// Raised when the collection is about to be cleared
///
/// This could be covered by calling ItemRemoved for each item currently
@@ -58,7 +63,7 @@ namespace Nuclex.Support.Collections {
#endif
/// Initializes a new ObservableCollection with no items
- public ObservableCollection() : this(new Collection()) {}
+ public ObservableCollection() : this(new Collection()) { }
///
/// Initializes a new ObservableCollection as a wrapper for an existing collection
@@ -75,11 +80,6 @@ namespace Nuclex.Support.Collections {
OnClearing();
this.typedCollection.Clear();
OnCleared();
-#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null) {
- CollectionChanged(this, CollectionResetEventArgs);
- }
-#endif
}
/// Adds an item to the collection
@@ -87,14 +87,6 @@ namespace Nuclex.Support.Collections {
public void Add(TItem item) {
this.typedCollection.Add(item);
OnAdded(item);
-#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null) {
- CollectionChanged(
- this,
- new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)
- );
- }
-#endif
}
/// Determines whether the collection contains the specified item
@@ -132,14 +124,6 @@ namespace Nuclex.Support.Collections {
bool wasRemoved = this.typedCollection.Remove(item);
if(wasRemoved) {
OnRemoved(item);
-#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null) {
- CollectionChanged(
- this,
- new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)
- );
- }
-#endif
}
return wasRemoved;
@@ -154,27 +138,52 @@ namespace Nuclex.Support.Collections {
/// Fires the 'ItemAdded' event
/// Item that has been added to the collection
protected virtual void OnAdded(TItem item) {
- if(ItemAdded != null)
+ if(ItemAdded != null) {
ItemAdded(this, new ItemEventArgs(item));
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
+ CollectionChanged(
+ this,
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)
+ );
+ }
+#endif
}
/// Fires the 'ItemRemoved' event
/// Item that has been removed from the collection
protected virtual void OnRemoved(TItem item) {
- if(ItemRemoved != null)
+ if(ItemRemoved != null) {
ItemRemoved(this, new ItemEventArgs(item));
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
+ CollectionChanged(
+ this,
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)
+ );
+ }
+#endif
}
/// Fires the 'Clearing' event
protected virtual void OnClearing() {
- if(Clearing != null)
+ if(Clearing != null) {
Clearing(this, EventArgs.Empty);
+ }
}
/// Fires the 'Cleared' event
protected virtual void OnCleared() {
- if(Cleared != null)
+ if(Cleared != null) {
Cleared(this, EventArgs.Empty);
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
+ CollectionChanged(this, Constants.NotifyCollectionResetEventArgs);
+ }
+#endif
}
#region IEnumerable implementation
@@ -212,12 +221,6 @@ namespace Nuclex.Support.Collections {
#endregion // IEnumerable implementation
-#if !NO_SPECIALIZED_COLLECTIONS
- /// Fixed event args used to notify that the collection has reset
- private static readonly NotifyCollectionChangedEventArgs CollectionResetEventArgs =
- new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
-#endif
-
/// The wrapped collection under its type-safe interface
private ICollection typedCollection;
/// The wrapped collection under its object interface
diff --git a/Source/Collections/ObservableDictionary.cs b/Source/Collections/ObservableDictionary.cs
index 05d8cf0..d5274fe 100644
--- a/Source/Collections/ObservableDictionary.cs
+++ b/Source/Collections/ObservableDictionary.cs
@@ -36,15 +36,15 @@ namespace Nuclex.Support.Collections {
#endif
public class ObservableDictionary :
#if !NO_SERIALIZATION
- ISerializable,
+ ISerializable,
IDeserializationCallback,
#endif
- IDictionary,
+ IDictionary,
IDictionary,
#if !NO_SPECIALIZED_COLLECTIONS
- INotifyCollectionChanged,
+ INotifyCollectionChanged,
#endif
- IObservableCollection> {
+ IObservableCollection> {
#if !NO_SERIALIZATION
#region class SerializedDictionary
@@ -81,6 +81,8 @@ namespace Nuclex.Support.Collections {
public event EventHandler>> ItemAdded;
/// Raised when an item is removed from the dictionary
public event EventHandler>> ItemRemoved;
+ /// Raised when an item is replaced in the collection
+ public event EventHandler>> ItemReplaced;
/// Raised when the dictionary is about to be cleared
public event EventHandler Clearing;
/// Raised when the dictionary has been cleared
@@ -202,9 +204,13 @@ namespace Nuclex.Support.Collections {
this.typedDictionary[key] = value;
if(removed) {
- OnRemoved(new KeyValuePair(key, oldValue));
+ OnReplaced(
+ new KeyValuePair(key, oldValue),
+ new KeyValuePair(key, value)
+ );
+ } else {
+ OnAdded(new KeyValuePair(key, value));
}
- OnAdded(new KeyValuePair(key, value));
}
}
@@ -244,28 +250,51 @@ namespace Nuclex.Support.Collections {
ItemAdded(this, new ItemEventArgs>(item));
#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null)
+ if(CollectionChanged != null) {
CollectionChanged(
- this, new NotifyCollectionChangedEventArgs(
- NotifyCollectionChangedAction.Add, item
- )
+ this,
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)
);
+ }
#endif
}
/// Fires the 'ItemRemoved' event
/// Item that has been removed from the collection
protected virtual void OnRemoved(KeyValuePair item) {
- if(ItemRemoved != null)
+ if(ItemRemoved != null) {
ItemRemoved(this, new ItemEventArgs>(item));
-
+ }
#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null)
+ if(CollectionChanged != null) {
+ CollectionChanged(
+ this,
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)
+ );
+ }
+#endif
+ }
+
+ /// Fires the 'ItemReplaced' event
+ /// Item that has been replaced in the collection
+ /// Item with which the original item was replaced
+ protected virtual void OnReplaced(
+ KeyValuePair oldItem, KeyValuePair newItem
+ ) {
+ if(ItemReplaced != null) {
+ ItemReplaced(
+ this,
+ new ItemReplaceEventArgs>(oldItem, newItem)
+ );
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
CollectionChanged(
this, new NotifyCollectionChangedEventArgs(
- NotifyCollectionChangedAction.Remove, item
+ NotifyCollectionChangedAction.Replace, newItem, oldItem
)
);
+ }
#endif
}
@@ -281,8 +310,9 @@ namespace Nuclex.Support.Collections {
Cleared(this, EventArgs.Empty);
#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null)
- CollectionChanged(this, CollectionResetEventArgs);
+ if(CollectionChanged != null) {
+ CollectionChanged(this, Constants.NotifyCollectionResetEventArgs);
+ }
#endif
}
@@ -449,12 +479,6 @@ namespace Nuclex.Support.Collections {
/// The wrapped Dictionary under its object interface
private IDictionary objectDictionary;
-#if !NO_SPECIALIZED_COLLECTIONS
- /// Fixed event args used to notify that the collection has reset
- private static readonly NotifyCollectionChangedEventArgs CollectionResetEventArgs =
- new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
-#endif
-
}
} // namespace Nuclex.Support.Collections
diff --git a/Source/Collections/ObservableList.cs b/Source/Collections/ObservableList.cs
index eefbcfd..a04a7c1 100644
--- a/Source/Collections/ObservableList.cs
+++ b/Source/Collections/ObservableList.cs
@@ -30,16 +30,21 @@ namespace Nuclex.Support.Collections {
/// List which fires events when items are added or removed
/// Type of items the collection manages
- public class ObservableList : IList, IList, ICollection,
+ public class ObservableList :
+ IList,
+ IList,
+ ICollection,
#if !NO_SPECIALIZED_COLLECTIONS
- INotifyCollectionChanged,
+ INotifyCollectionChanged,
#endif
- IObservableCollection {
+ IObservableCollection {
/// Raised when an item has been added to the collection
public event EventHandler> ItemAdded;
/// Raised when an item is removed from the collection
public event EventHandler> ItemRemoved;
+ /// Raised when an item is replaced in the collection
+ public event EventHandler> ItemReplaced;
/// Raised when the collection is about to be cleared
///
/// This could be covered by calling ItemRemoved for each item currently
@@ -83,10 +88,7 @@ namespace Nuclex.Support.Collections {
/// Item that will be inserted into the list
public void Insert(int index, TItem item) {
this.typedList.Insert(index, item);
- OnAdded(item);
-#if !NO_SPECIALIZED_COLLECTIONS
- OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
-#endif
+ OnAdded(item, index);
}
/// Removes the item at the specified index from the list
@@ -94,10 +96,7 @@ namespace Nuclex.Support.Collections {
public void RemoveAt(int index) {
TItem item = this.typedList[index];
this.typedList.RemoveAt(index);
- OnRemoved(item);
-#if !NO_SPECIALIZED_COLLECTIONS
- OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
-#endif
+ OnRemoved(item, index);
}
/// Accesses the item at the specified index in the list
@@ -108,18 +107,7 @@ namespace Nuclex.Support.Collections {
set {
TItem oldItem = this.typedList[index];
this.typedList[index] = value;
- OnRemoved(oldItem);
- OnAdded(value);
-#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null) {
- CollectionChanged(
- this, new NotifyCollectionChangedEventArgs(
- NotifyCollectionChangedAction.Replace, value, oldItem, index
- )
- );
- }
-#endif
-
+ OnReplaced(oldItem, value, index);
}
}
@@ -127,7 +115,7 @@ namespace Nuclex.Support.Collections {
/// Item that will be added to the list
public void Add(TItem item) {
this.typedList.Add(item);
- OnAdded(item);
+ OnAdded(item, this.typedList.Count - 1);
}
/// Removes all items from the list
@@ -135,11 +123,6 @@ namespace Nuclex.Support.Collections {
OnClearing();
this.typedList.Clear();
OnCleared();
-#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null) {
- CollectionChanged(this, CollectionResetEventArgs);
- }
-#endif
}
/// Checks whether the list contains the specified item
@@ -181,10 +164,8 @@ namespace Nuclex.Support.Collections {
TItem removedItem = this.typedList[index];
this.typedList.RemoveAt(index);
- OnRemoved(removedItem);
-#if !NO_SPECIALIZED_COLLECTIONS
- OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
-#endif
+ OnRemoved(removedItem, index);
+
return true;
}
@@ -237,10 +218,7 @@ namespace Nuclex.Support.Collections {
int IList.Add(object value) {
int index = this.objectList.Add(value);
TItem addedItem = this.typedList[index];
- OnAdded(addedItem);
-#if !NO_SPECIALIZED_COLLECTIONS
- OnCollectionChanged(NotifyCollectionChangedAction.Add, addedItem, index);
-#endif
+ OnAdded(addedItem, index);
return index;
}
@@ -264,10 +242,7 @@ namespace Nuclex.Support.Collections {
void IList.Insert(int index, object item) {
this.objectList.Insert(index, item);
TItem addedItem = this.typedList[index];
- OnAdded(addedItem);
-#if !NO_SPECIALIZED_COLLECTIONS
- OnCollectionChanged(NotifyCollectionChangedAction.Add, addedItem, index);
-#endif
+ OnAdded(addedItem, index);
}
/// Whether the list is of a fixed size
@@ -285,10 +260,7 @@ namespace Nuclex.Support.Collections {
TItem removedItem = this.typedList[index];
this.objectList.RemoveAt(index);
- OnRemoved(removedItem);
-#if !NO_SPECIALIZED_COLLECTIONS
- OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
-#endif
+ OnRemoved(removedItem, index);
}
/// Accesses the item at the specified index in the list
@@ -300,69 +272,84 @@ namespace Nuclex.Support.Collections {
TItem oldItem = this.typedList[index];
this.objectList[index] = value;
TItem newItem = this.typedList[index];
- OnRemoved(oldItem);
- OnAdded(newItem);
-#if !NO_SPECIALIZED_COLLECTIONS
- if(CollectionChanged != null) {
- CollectionChanged(
- this, new NotifyCollectionChangedEventArgs(
- NotifyCollectionChangedAction.Replace, newItem, oldItem, index
- )
- );
- }
-#endif
+ OnReplaced(oldItem, newItem, index);
}
}
#endregion // IList implementation
-#if !NO_SPECIALIZED_COLLECTIONS
- /// Fires the CollectionChanged event
- /// Type of change that has occured
- /// The item that has been added, removed or replaced
- /// Index of the changed item
- protected virtual void OnCollectionChanged(
- NotifyCollectionChangedAction action, TItem item, int index
- ) {
- if(CollectionChanged != null) {
- CollectionChanged(
- this, new NotifyCollectionChangedEventArgs(action, item, index)
- );
- }
- }
-#endif
-
/// Fires the 'ItemAdded' event
/// Item that has been added to the collection
- protected virtual void OnAdded(TItem item) {
- if(ItemAdded != null)
+ /// Index of the added item
+ protected virtual void OnAdded(TItem item, int index) {
+ if(ItemAdded != null) {
ItemAdded(this, new ItemEventArgs(item));
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
+ CollectionChanged(
+ this,
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)
+ );
+ }
+#endif
}
/// Fires the 'ItemRemoved' event
/// Item that has been removed from the collection
- protected virtual void OnRemoved(TItem item) {
- if(ItemRemoved != null)
+ /// Index the item has been removed from
+ protected virtual void OnRemoved(TItem item, int index) {
+ if(ItemRemoved != null) {
ItemRemoved(this, new ItemEventArgs(item));
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
+ CollectionChanged(
+ this,
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)
+ );
+ }
+#endif
+ }
+
+ /// Fires the 'ItemReplaced' event
+ /// Item that has been replaced
+ /// New item the original item was replaced with
+ /// Index of the replaced item
+ protected virtual void OnReplaced(TItem oldItem, TItem newItem, int index) {
+ if(ItemReplaced != null) {
+ ItemReplaced(this, new ItemReplaceEventArgs(oldItem, newItem));
+ }
+#if !NO_SPECIALIZED_COLLECTIONS
+ if(CollectionChanged != null) {
+ CollectionChanged(
+ this,
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Replace, newItem, oldItem, index
+ )
+ );
+ }
+#endif
}
/// Fires the 'Clearing' event
protected virtual void OnClearing() {
- if(Clearing != null)
+ if(Clearing != null) {
Clearing(this, EventArgs.Empty);
+ }
}
/// Fires the 'Cleared' event
protected virtual void OnCleared() {
- if(Cleared != null)
+ if(Cleared != null) {
Cleared(this, EventArgs.Empty);
- }
-
+ }
#if !NO_SPECIALIZED_COLLECTIONS
- /// Fixed event args used to notify that the collection has reset
- private static readonly NotifyCollectionChangedEventArgs CollectionResetEventArgs =
- new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
+ if(CollectionChanged != null) {
+ CollectionChanged(this, Constants.NotifyCollectionResetEventArgs);
+ }
#endif
+ }
/// The wrapped list under its type-safe interface
private IList typedList;