Index: trunk/sources/HeuristicLab.Collections/3.3/HeuristicLab.Collections-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/HeuristicLab.Collections-3.3.csproj	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/HeuristicLab.Collections-3.3.csproj	(revision 2623)
@@ -49,4 +49,9 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ReadOnlyObservableSet.cs" />
+    <Compile Include="IObservableSet.cs" />
+    <Compile Include="ObservableSet.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="ReadOnlyObservableKeyedCollection.cs">
       <SubType>Code</SubType>
Index: trunk/sources/HeuristicLab.Collections/3.3/IObservableDictionary.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IObservableDictionary.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableDictionary.cs	(revision 2623)
@@ -27,9 +27,6 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyPropertyChanged {
-    event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsAdded;
-    event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsRemoved;
+  public interface IObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IObservableCollection<KeyValuePair<TKey, TValue>> {
     event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsReplaced;
-    event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> CollectionReset;
   }
 }
Index: trunk/sources/HeuristicLab.Collections/3.3/IObservableKeyedCollection.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IObservableKeyedCollection.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableKeyedCollection.cs	(revision 2623)
@@ -27,5 +27,5 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableKeyedCollection<TKey, TItem> : ICollection<TItem>, INotifyPropertyChanged {
+  public interface IObservableKeyedCollection<TKey, TItem> : IObservableCollection<TItem> {
     TItem this[TKey key] { get; }
 
@@ -33,8 +33,7 @@
     bool TryGetValue(TKey key, out TItem item);
 
-    event CollectionItemsChangedEventHandler<TItem> ItemsAdded;
-    event CollectionItemsChangedEventHandler<TItem> ItemsRemoved;
+    bool Remove(TKey key);
+
     event CollectionItemsChangedEventHandler<TItem> ItemsReplaced;
-    event CollectionItemsChangedEventHandler<TItem> CollectionReset;
   }
 }
Index: trunk/sources/HeuristicLab.Collections/3.3/IObservableList.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IObservableList.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableList.cs	(revision 2623)
@@ -27,10 +27,10 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableList<T> : IList<T>, INotifyPropertyChanged {
-    event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsAdded;
-    event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
+  public interface IObservableList<T> : IList<T>, IObservableCollection<T> {
+    new event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsAdded;
+    new event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
     event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
     event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsMoved;
-    event CollectionItemsChangedEventHandler<IndexedItem<T>> CollectionReset;
+    new event CollectionItemsChangedEventHandler<IndexedItem<T>> CollectionReset;
   }
 }
Index: trunk/sources/HeuristicLab.Collections/3.3/IObservableSet.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IObservableSet.cs	(revision 2623)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableSet.cs	(revision 2623)
@@ -0,0 +1,47 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+
+namespace HeuristicLab.Collections {
+  public interface IObservableSet<T> : IObservableCollection<T> {
+    bool IsProperSubsetOf(IEnumerable<T> other);
+    bool IsProperSupersetOf(IEnumerable<T> other);
+
+    bool IsSubsetOf(IEnumerable<T> other);
+    bool IsSupersetOf(IEnumerable<T> other);
+
+    bool Overlaps(IEnumerable<T> other);
+
+    bool SetEquals(IEnumerable<T> other);
+
+    new bool Add(T item);
+
+    void ExceptWith(IEnumerable<T> other);
+    void IntersectWith(IEnumerable<T> other);
+    void SymmetricExceptWith(IEnumerable<T> other);
+    void UnionWith(IEnumerable<T> other);
+  }
+}
Index: trunk/sources/HeuristicLab.Collections/3.3/IndexedItem.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IndexedItem.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/IndexedItem.cs	(revision 2623)
@@ -44,5 +44,7 @@
     public override string ToString() {
       StringBuilder sb = new StringBuilder();
-      sb.Append("[").Append(index).Append(", ").Append(value != null ? value.ToString() : "null").Append("]");
+      sb.Append("[").Append(index).Append(", ");
+      if (value != null) sb.Append(value.ToString());
+      sb.Append("]");
       return sb.ToString();
     }
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableDictionary.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableDictionary.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableDictionary.cs	(revision 2623)
@@ -173,12 +173,9 @@
 
     #region Enumeration
-    public Dictionary<TKey, TValue>.Enumerator GetEnumerator() {
+    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
       return dict.GetEnumerator();
     }
-    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() {
-      return ((IEnumerable<KeyValuePair<TKey, TValue>>)dict).GetEnumerator();
-    }
     IEnumerator IEnumerable.GetEnumerator() {
-      return ((IEnumerable)dict).GetEnumerator();
+      return dict.GetEnumerator();
     }
     #endregion
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs	(revision 2623)
@@ -77,4 +77,5 @@
       list = new List<T>(collection);
       OnItemsAdded(GetIndexedItems());
+      OnItemsAdded(collection);
     }
     #endregion
@@ -163,4 +164,5 @@
       OnPropertyChanged("Count");
       OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(list.Count - 1, item) });
+      OnItemsAdded(new T[] { item });
     }
     public void AddRange(IEnumerable<T> collection) {
@@ -179,4 +181,5 @@
         OnPropertyChanged("Count");
         OnItemsAdded(items);
+        OnItemsAdded(collection);
       }
     }
@@ -190,4 +193,5 @@
       OnPropertyChanged("Count");
       OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
+      OnItemsAdded(new T[] { item });
     }
     public void InsertRange(int index, IEnumerable<T> collection) {
@@ -205,4 +209,5 @@
         OnPropertyChanged("Count");
         OnItemsAdded(items);
+        OnItemsAdded(collection);
       }
     }
@@ -215,4 +220,5 @@
         OnPropertyChanged("Count");
         OnItemsRemoved(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
+        OnItemsRemoved(new T[] { item });
         return true;
       }
@@ -221,14 +227,18 @@
     public int RemoveAll(Predicate<T> match) {
       if (match == null) throw new ArgumentNullException();
-      List<IndexedItem<T>> items = new List<IndexedItem<T>>();
+      List<IndexedItem<T>> indexedItems = new List<IndexedItem<T>>();
+      List<T> items = new List<T>();
       for (int i = 0; i < list.Count; i++) {
-        if (match(list[i]))
-          items.Add(new IndexedItem<T>(i, list[i]));
+        if (match(list[i])) {
+          indexedItems.Add(new IndexedItem<T>(i, list[i]));
+          items.Add(list[i]);
+        }
       }
       int result = 0;
-      if (items.Count > 0) {
+      if (indexedItems.Count > 0) {
         result = list.RemoveAll(match);
         OnPropertyChanged("Item[]");
         OnPropertyChanged("Count");
+        OnItemsRemoved(indexedItems);
         OnItemsRemoved(items);
       }
@@ -241,11 +251,15 @@
       OnPropertyChanged("Count");
       OnItemsRemoved(new IndexedItem<T>[] { new IndexedItem<T>(index, item) });
+      OnItemsRemoved(new T[] { item });
     }
     public void RemoveRange(int index, int count) {
       if (count > 0) {
-        IndexedItem<T>[] items = GetIndexedItems(index, count);
+        IndexedItem<T>[] indexedItems = GetIndexedItems(index, count);
+        T[] items = new T[count];
+        list.CopyTo(index, items, 0, count);
         list.RemoveRange(index, count);
         OnPropertyChanged("Item[]");
         OnPropertyChanged("Count");
+        OnItemsRemoved(indexedItems);
         OnItemsRemoved(items);
       }
@@ -254,9 +268,11 @@
     public void Clear() {
       if (list.Count > 0) {
-        IndexedItem<T>[] items = GetIndexedItems();
+        IndexedItem<T>[] indexedItems = GetIndexedItems();
+        T[] items = list.ToArray();
         list.Clear();
         OnPropertyChanged("Item[]");
         OnPropertyChanged("Count");
-        OnCollectionReset(new IndexedItem<T>[0], items);
+        OnCollectionReset(new IndexedItem<T>[0], indexedItems);
+        OnCollectionReset(new T[0], items);
       }
     }
@@ -320,6 +336,12 @@
       return list.ToArray();
     }
-    void ICollection<T>.CopyTo(T[] array, int arrayIndex) {
+    public void CopyTo(T[] array) {
+      list.CopyTo(array);
+    }
+    public void CopyTo(T[] array, int arrayIndex) {
       list.CopyTo(array, arrayIndex);
+    }
+    public void CopyTo(int index, T[] array, int arrayIndex, int count) {
+      list.CopyTo(index, array, arrayIndex, count);
     }
     public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) {
@@ -338,12 +360,9 @@
 
     #region Enumeration
-    public List<T>.Enumerator GetEnumerator() {
+    public IEnumerator<T> GetEnumerator() {
       return list.GetEnumerator();
     }
-    IEnumerator<T> IEnumerable<T>.GetEnumerator() {
-      return ((IEnumerable<T>)list).GetEnumerator();
-    }
     IEnumerator IEnumerable.GetEnumerator() {
-      return ((IEnumerable)list).GetEnumerator();
+      return list.GetEnumerator();
     }
     #endregion
@@ -367,4 +386,15 @@
 
     [field: NonSerialized]
+    private event CollectionItemsChangedEventHandler<T> itemsAdded;
+    event CollectionItemsChangedEventHandler<T> IObservableCollection<T>.ItemsAdded {
+      add { itemsAdded += value; }
+      remove { itemsAdded -= value; }
+    }
+    private void OnItemsAdded(IEnumerable<T> items) {
+      if (itemsAdded != null)
+        itemsAdded(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
     public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
     protected virtual void OnItemsRemoved(IEnumerable<IndexedItem<T>> items) {
@@ -374,4 +404,15 @@
 
     [field: NonSerialized]
+    private event CollectionItemsChangedEventHandler<T> itemsRemoved;
+    event CollectionItemsChangedEventHandler<T> IObservableCollection<T>.ItemsRemoved {
+      add { itemsRemoved += value; }
+      remove { itemsRemoved -= value; }
+    }
+    private void OnItemsRemoved(IEnumerable<T> items) {
+      if (itemsRemoved != null)
+        itemsRemoved(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
     public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
     protected virtual void OnItemsReplaced(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
@@ -392,4 +433,15 @@
       if (CollectionReset != null)
         CollectionReset(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    private event CollectionItemsChangedEventHandler<T> collectionReset;
+    event CollectionItemsChangedEventHandler<T> IObservableCollection<T>.CollectionReset {
+      add { collectionReset += value; }
+      remove { collectionReset -= value; }
+    }
+    private void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
+      if (collectionReset != null)
+        collectionReset(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
     }
 
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableSet.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableSet.cs	(revision 2623)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableSet.cs	(revision 2623)
@@ -0,0 +1,260 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Collections {
+  [Serializable]
+  public class ObservableSet<T> : IObservableSet<T> {
+    [Storable]
+    private HashSet<T> set;
+
+    #region Properties
+    public IEqualityComparer<T> Comparer {
+      get { return set.Comparer; }
+    }
+    public int Count {
+      get { return set.Count; }
+    }
+    bool ICollection<T>.IsReadOnly {
+      get { return ((ICollection<T>)set).IsReadOnly; }
+    }
+    #endregion
+
+    #region Constructors
+    public ObservableSet() {
+      set = new HashSet<T>();
+    }
+    public ObservableSet(IEnumerable<T> collection) {
+      set = new HashSet<T>(collection);
+      OnItemsAdded(this);
+    }
+    public ObservableSet(IEqualityComparer<T> comparer) {
+      set = new HashSet<T>(comparer);
+    }
+    public ObservableSet(IEnumerable<T> collection, IEqualityComparer<T> comparer) {
+      set = new HashSet<T>(collection, comparer);
+      OnItemsAdded(this);
+    }
+    #endregion
+
+    #region Access
+    public bool Contains(T item) {
+      return set.Contains(item);
+    }
+
+    public bool IsProperSubsetOf(IEnumerable<T> other) {
+      return set.IsProperSubsetOf(other);
+    }
+    public bool IsProperSupersetOf(IEnumerable<T> other) {
+      return set.IsProperSupersetOf(other);
+    }
+
+    public bool IsSubsetOf(IEnumerable<T> other) {
+      return set.IsSubsetOf(other);
+    }
+    public bool IsSupersetOf(IEnumerable<T> other) {
+      return set.IsSupersetOf(other);
+    }
+
+    public bool Overlaps(IEnumerable<T> other) {
+      return set.Overlaps(other);
+    }
+
+    public bool SetEquals(IEnumerable<T> other) {
+      return set.SetEquals(other);
+    }
+    #endregion
+
+    #region Manipulation
+    public bool Add(T item) {
+      if (set.Add(item)) {
+        OnPropertyChanged("Count");
+        OnItemsAdded(new T[] { item });
+        return true;
+      }
+      return false;
+    }
+    void ICollection<T>.Add(T item) {
+      Add(item);
+    }
+
+    public void ExceptWith(IEnumerable<T> other) {
+      if (other == null) throw new ArgumentNullException();
+      List<T> items = new List<T>();
+      foreach (T item in other) {
+        if (set.Remove(item))
+          items.Add(item);
+      }
+      if (items.Count > 0) {
+        OnPropertyChanged("Count");
+        OnItemsRemoved(items);
+      }
+    }
+
+    public void IntersectWith(IEnumerable<T> other) {
+      if (other == null) throw new ArgumentNullException();
+      HashSet<T> items = new HashSet<T>();
+      foreach (T item in set) {
+        if (!other.Contains(item)) items.Add(item);
+      }
+      if (items.Count > 0) {
+        set.ExceptWith(items);
+        OnPropertyChanged("Count");
+        OnItemsRemoved(items);
+      }
+    }
+
+    public bool Remove(T item) {
+      if (set.Remove(item)) {
+        OnPropertyChanged("Count");
+        OnItemsRemoved(new T[] { item });
+        return true;
+      }
+      return false;
+    }
+    public int RemoveWhere(Predicate<T> match) {
+      if (match == null) throw new ArgumentNullException();
+      HashSet<T> items = new HashSet<T>();
+      foreach (T item in set) {
+        if (match(item)) items.Add(item);
+      }
+      if (items.Count > 0) {
+        set.ExceptWith(items);
+        OnPropertyChanged("Count");
+        OnItemsRemoved(items);
+      }
+      return items.Count;
+    }
+
+    public void SymmetricExceptWith(IEnumerable<T> other) {
+      if (other == null) throw new ArgumentNullException();
+      List<T> addedItems = new List<T>();
+      List<T> removedItems = new List<T>();
+      foreach (T item in other) {
+        if (set.Contains(item)) {
+          set.Remove(item);
+          removedItems.Add(item);
+        } else {
+          set.Add(item);
+          addedItems.Add(item);
+        }
+      }
+      if ((addedItems.Count > 0) || (removedItems.Count > 0)) {
+        OnPropertyChanged("Count");
+        if (addedItems.Count > 0) OnItemsAdded(addedItems);
+        if (removedItems.Count > 0) OnItemsRemoved(removedItems);
+      }
+    }
+
+    public void UnionWith(IEnumerable<T> other) {
+      if (other == null) throw new ArgumentNullException();
+      List<T> items = new List<T>();
+      foreach (T item in other) {
+        if (set.Add(item)) {
+          items.Add(item);
+        }
+      }
+      if (items.Count > 0) {
+        OnPropertyChanged("Count");
+        OnItemsAdded(items);
+      }
+    }
+
+    public void Clear() {
+      if (set.Count > 0) {
+        T[] items = new T[set.Count];
+        set.CopyTo(items);
+        set.Clear();
+        OnPropertyChanged("Count");
+        OnCollectionReset(new T[0], items);
+      }
+    }
+    #endregion
+
+    #region Conversion
+    public ReadOnlyObservableSet<T> AsReadOnly() {
+      return new ReadOnlyObservableSet<T>(this);
+    }
+    public void CopyTo(T[] array) {
+      set.CopyTo(array);
+    }
+    public void CopyTo(T[] array, int arrayIndex) {
+      set.CopyTo(array, arrayIndex);
+    }
+    public void CopyTo(T[] array, int arrayIndex, int count) {
+      set.CopyTo(array, arrayIndex, count);
+    }
+    #endregion
+
+    #region Enumeration
+    public IEnumerator<T> GetEnumerator() {
+      return set.GetEnumerator();
+    }
+    IEnumerator IEnumerable.GetEnumerator() {
+      return set.GetEnumerator();
+    }
+    #endregion
+
+    #region Helpers
+    public void TrimExcess() {
+      set.TrimExcess();
+    }
+    #endregion
+
+    #region Events
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<T> ItemsAdded;
+    protected virtual void OnItemsAdded(IEnumerable<T> items) {
+      if (ItemsAdded != null)
+        ItemsAdded(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<T> ItemsRemoved;
+    protected virtual void OnItemsRemoved(IEnumerable<T> items) {
+      if (ItemsRemoved != null)
+        ItemsRemoved(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<T> CollectionReset;
+    protected virtual void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
+      if (CollectionReset != null)
+        CollectionReset(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      if (PropertyChanged != null)
+        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableKeyedCollection.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableKeyedCollection.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableKeyedCollection.cs	(revision 2623)
@@ -80,4 +80,7 @@
     }
 
+    bool IObservableKeyedCollection<TKey, TItem>.Remove(TKey key) {
+      throw new NotSupportedException();
+    }
     bool ICollection<TItem>.Remove(TItem item) {
       throw new NotSupportedException();
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableList.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableList.cs	(revision 2622)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableList.cs	(revision 2623)
@@ -57,8 +57,11 @@
       this.list = list;
       list.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<T>>(list_ItemsAdded);
+      ((IObservableCollection<T>)list).ItemsAdded += new CollectionItemsChangedEventHandler<T>(list_ItemsAdded);
       list.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<T>>(list_ItemsRemoved);
+      ((IObservableCollection<T>)list).ItemsRemoved += new CollectionItemsChangedEventHandler<T>(list_ItemsRemoved);
       list.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<T>>(list_ItemsReplaced);
       list.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<T>>(list_ItemsMoved);
       list.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<T>>(list_CollectionReset);
+      ((IObservableCollection<T>)list).CollectionReset += new CollectionItemsChangedEventHandler<T>(list_CollectionReset);
       list.PropertyChanged += new PropertyChangedEventHandler(list_PropertyChanged);
     }
@@ -97,5 +100,5 @@
 
     #region Conversion
-    void ICollection<T>.CopyTo(T[] array, int arrayIndex) {
+    public void CopyTo(T[] array, int arrayIndex) {
       list.CopyTo(array, arrayIndex);
     }
@@ -120,4 +123,15 @@
 
     [field: NonSerialized]
+    private event CollectionItemsChangedEventHandler<T> itemsAdded;
+    event CollectionItemsChangedEventHandler<T> IObservableCollection<T>.ItemsAdded {
+      add { itemsAdded += value; }
+      remove { itemsAdded -= value; }
+    }
+    private void OnItemsAdded(IEnumerable<T> items) {
+      if (itemsAdded != null)
+        itemsAdded(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
     public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
     protected virtual void OnItemsRemoved(IEnumerable<IndexedItem<T>> items) {
@@ -127,4 +141,15 @@
 
     [field: NonSerialized]
+    private event CollectionItemsChangedEventHandler<T> itemsRemoved;
+    event CollectionItemsChangedEventHandler<T> IObservableCollection<T>.ItemsRemoved {
+      add { itemsRemoved += value; }
+      remove { itemsRemoved -= value; }
+    }
+    private void OnItemsRemoved(IEnumerable<T> items) {
+      if (itemsRemoved != null)
+        itemsRemoved(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
     public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
     protected virtual void OnItemsReplaced(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
@@ -148,4 +173,15 @@
 
     [field: NonSerialized]
+    private event CollectionItemsChangedEventHandler<T> collectionReset;
+    event CollectionItemsChangedEventHandler<T> IObservableCollection<T>.CollectionReset {
+      add { collectionReset += value; }
+      remove { collectionReset -= value; }
+    }
+    private void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
+      if (collectionReset != null)
+        collectionReset(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
+    }
+
+    [field: NonSerialized]
     public event PropertyChangedEventHandler PropertyChanged;
     protected virtual void OnPropertyChanged(string propertyName) {
@@ -157,7 +193,13 @@
       OnItemsAdded(e.Items);
     }
+    private void list_ItemsAdded(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnItemsAdded(e.Items);
+    }
     private void list_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
       OnItemsRemoved(e.Items);
     }
+    private void list_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnItemsRemoved(e.Items);
+    }
     private void list_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
       OnItemsReplaced(e.Items, e.OldItems);
@@ -167,4 +209,7 @@
     }
     private void list_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      OnCollectionReset(e.Items, e.OldItems);
+    }
+    private void list_CollectionReset(object sender, CollectionItemsChangedEventArgs<T> e) {
       OnCollectionReset(e.Items, e.OldItems);
     }
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableSet.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableSet.cs	(revision 2623)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableSet.cs	(revision 2623)
@@ -0,0 +1,177 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Collections {
+  [Serializable]
+  public class ReadOnlyObservableSet<T> : IObservableSet<T> {
+    [Storable]
+    private IObservableSet<T> set;
+
+    #region Properties
+    public int Count {
+      get { return set.Count; }
+    }
+    bool ICollection<T>.IsReadOnly {
+      get { return true; }
+    }
+    #endregion
+
+    #region Constructors
+    public ReadOnlyObservableSet(IObservableSet<T> set) {
+      if (set == null) throw new ArgumentNullException();
+      this.set = set;
+      set.ItemsAdded += new CollectionItemsChangedEventHandler<T>(set_ItemsAdded);
+      set.ItemsRemoved += new CollectionItemsChangedEventHandler<T>(set_ItemsRemoved);
+      set.CollectionReset += new CollectionItemsChangedEventHandler<T>(set_CollectionReset);
+      set.PropertyChanged += new PropertyChangedEventHandler(set_PropertyChanged);
+    }
+    #endregion
+
+    #region Access
+    public bool Contains(T item) {
+      return set.Contains(item);
+    }
+
+    public bool IsProperSubsetOf(IEnumerable<T> other) {
+      return set.IsProperSubsetOf(other);
+    }
+    public bool IsProperSupersetOf(IEnumerable<T> other) {
+      return set.IsProperSupersetOf(other);
+    }
+
+    public bool IsSubsetOf(IEnumerable<T> other) {
+      return set.IsSubsetOf(other);
+    }
+    public bool IsSupersetOf(IEnumerable<T> other) {
+      return set.IsSupersetOf(other);
+    }
+
+    public bool Overlaps(IEnumerable<T> other) {
+      return set.Overlaps(other);
+    }
+
+    public bool SetEquals(IEnumerable<T> other) {
+      return set.SetEquals(other);
+    }
+    #endregion
+
+    #region Manipulation
+    bool IObservableSet<T>.Add(T item) {
+      throw new NotSupportedException();
+    }
+    void ICollection<T>.Add(T item) {
+      throw new NotSupportedException();
+    }
+
+    void IObservableSet<T>.ExceptWith(IEnumerable<T> other) {
+      throw new NotSupportedException();
+    }
+
+    void IObservableSet<T>.IntersectWith(IEnumerable<T> other) {
+      throw new NotSupportedException();
+    }
+
+    bool ICollection<T>.Remove(T item) {
+      throw new NotSupportedException();
+    }
+
+    void IObservableSet<T>.SymmetricExceptWith(IEnumerable<T> other) {
+      throw new NotSupportedException();
+    }
+
+    void IObservableSet<T>.UnionWith(IEnumerable<T> other) {
+      throw new NotSupportedException();
+    }
+
+    void ICollection<T>.Clear() {
+      throw new NotSupportedException();
+    }
+    #endregion
+
+    #region Conversion
+    public void CopyTo(T[] array, int arrayIndex) {
+      set.CopyTo(array, arrayIndex);
+    }
+    #endregion
+
+    #region Enumeration
+    public IEnumerator<T> GetEnumerator() {
+      return set.GetEnumerator();
+    }
+    IEnumerator IEnumerable.GetEnumerator() {
+      return set.GetEnumerator();
+    }
+    #endregion
+
+    #region Events
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<T> ItemsAdded;
+    protected virtual void OnItemsAdded(IEnumerable<T> items) {
+      if (ItemsAdded != null)
+        ItemsAdded(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<T> ItemsRemoved;
+    protected virtual void OnItemsRemoved(IEnumerable<T> items) {
+      if (ItemsRemoved != null)
+        ItemsRemoved(this, new CollectionItemsChangedEventArgs<T>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<T> CollectionReset;
+    protected virtual void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
+      if (CollectionReset != null)
+        CollectionReset(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    public event PropertyChangedEventHandler PropertyChanged;
+    protected virtual void OnPropertyChanged(string propertyName) {
+      if (PropertyChanged != null)
+        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+    }
+
+    private void set_ItemsAdded(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnItemsAdded(e.Items);
+    }
+    private void set_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnItemsRemoved(e.Items);
+    }
+    private void set_CollectionReset(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnCollectionReset(e.Items, e.OldItems);
+    }
+    private void set_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      if (e.PropertyName.Equals("Count"))
+        OnPropertyChanged(e.PropertyName);
+    }
+    #endregion
+  }
+}
