Index: trunk/sources/HeuristicLab.Collections/3.3/HeuristicLab.Collections-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/HeuristicLab.Collections-3.3.csproj	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/HeuristicLab.Collections-3.3.csproj	(revision 2618)
@@ -49,4 +49,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ReadOnlyObservableKeyedCollection.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="ReadOnlyObservableList.cs" />
+    <Compile Include="ReadOnlyObservableDictionary.cs" />
+    <Compile Include="ReadOnlyObservableCollection.cs" />
     <Compile Include="IObservableKeyedCollection.cs" />
     <Compile Include="IObservableList.cs" />
Index: trunk/sources/HeuristicLab.Collections/3.3/HeuristicLabCollectionsPlugin.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/HeuristicLabCollectionsPlugin.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/HeuristicLabCollectionsPlugin.cs	(revision 2618)
@@ -29,7 +29,7 @@
   /// Plugin class for HeuristicLab.Collections plugin.
   /// </summary>
-  [ClassInfo(Name = "HeuristicLab.Collections-3.2")]
-  [PluginFile(Filename = "HeuristicLab.Collections-3.3.dll", Filetype = PluginFileType.Assembly)]
-  [Dependency(Dependency = "HeuristicLab.Persistence-3.3")]
+  [Plugin("HeuristicLab.Collections-3.3")]
+  [PluginFile("HeuristicLab.Collections-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Persistence-3.3")]
   public class HeuristicLabCollectionsPlugin : PluginBase {
   }
Index: trunk/sources/HeuristicLab.Collections/3.3/IObservableCollection.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IObservableCollection.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableCollection.cs	(revision 2618)
@@ -26,5 +26,5 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableCollection<T> : ICollection<T>, IDisposable {
+  public interface IObservableCollection<T> : ICollection<T> {
     event CollectionItemsChangedEventHandler<T> ItemsAdded;
     event CollectionItemsChangedEventHandler<T> ItemsRemoved;
Index: trunk/sources/HeuristicLab.Collections/3.3/IObservableDictionary.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/IObservableDictionary.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableDictionary.cs	(revision 2618)
@@ -26,6 +26,9 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IObservableCollection<KeyValuePair<TKey, TValue>> {
+  public interface IObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue> {
+    event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsAdded;
+    event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsRemoved;
     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 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableKeyedCollection.cs	(revision 2618)
@@ -26,6 +26,14 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableKeyedCollection<TKey, TItem> : IObservableCollection<TItem> {
+  public interface IObservableKeyedCollection<TKey, TItem> : ICollection<TItem> {
+    TItem this[TKey key] { get; }
+
+    bool ContainsKey(TKey key);
+    bool TryGetValue(TKey key, out TItem item);
+
+    event CollectionItemsChangedEventHandler<TItem> ItemsAdded;
+    event CollectionItemsChangedEventHandler<TItem> ItemsRemoved;
     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 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/IObservableList.cs	(revision 2618)
@@ -26,7 +26,10 @@
 
 namespace HeuristicLab.Collections {
-  public interface IObservableList<T> : IList<T>, IObservableCollection<IndexedItem<T>> {
+  public interface IObservableList<T> : IList<T> {
+    event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsAdded;
+    event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
     event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
     event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsMoved;
+    event CollectionItemsChangedEventHandler<IndexedItem<T>> CollectionReset;
   }
 }
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableCollection.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableCollection.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableCollection.cs	(revision 2618)
@@ -42,5 +42,5 @@
       get { return list.Count; }
     }
-    public bool IsReadOnly {
+    bool ICollection<T>.IsReadOnly {
       get { return ((ICollection<T>)list).IsReadOnly; }
     }
@@ -57,19 +57,4 @@
       list = new List<T>(collection);
       OnItemsAdded(collection);
-    }
-    #endregion
-
-    #region Destructors
-    ~ObservableCollection() {
-      Dispose(false);
-    }
-    protected virtual void Dispose(bool disposing) {
-      if (disposing) {
-        Clear();
-      }
-    }
-    public void Dispose() {
-      Dispose(true);
-      GC.SuppressFinalize(this);
     }
     #endregion
@@ -137,6 +122,6 @@
 
     #region Conversion
-    public ReadOnlyCollection<T> AsReadOnly() {
-      return list.AsReadOnly();
+    public ReadOnlyObservableCollection<T> AsReadOnly() {
+      return new ReadOnlyObservableCollection<T>(this);
     }
     public T[] ToArray() {
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableDictionary.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableDictionary.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableDictionary.cs	(revision 2618)
@@ -91,19 +91,4 @@
     #endregion
 
-    #region Destructors
-    ~ObservableDictionary() {
-      Dispose(false);
-    }
-    protected virtual void Dispose(bool disposing) {
-      if (disposing) {
-        Clear();
-      }
-    }
-    public void Dispose() {
-      Dispose(true);
-      GC.SuppressFinalize(this);
-    }
-    #endregion
-
     #region Access
     public bool ContainsKey(TKey key) {
@@ -157,4 +142,7 @@
 
     #region Conversion
+    public ReadOnlyObservableDictionary<TKey, TValue> AsReadOnly() {
+      return new ReadOnlyObservableDictionary<TKey, TValue>(this);
+    }
     void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
       ((ICollection<KeyValuePair<TKey, TValue>>)dict).CopyTo(array, arrayIndex);
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableKeyedCollectionBase.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableKeyedCollectionBase.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableKeyedCollectionBase.cs	(revision 2618)
@@ -41,5 +41,5 @@
       get { return dict.Comparer; }
     }
-    public bool IsReadOnly {
+    bool ICollection<TItem>.IsReadOnly {
       get { return ((ICollection<KeyValuePair<TKey, TItem>>)dict).IsReadOnly; }
     }
@@ -78,19 +78,4 @@
         dict.Add(GetKeyForItem(item), item);
       OnItemsAdded(collection);
-    }
-    #endregion
-
-    #region Destructors
-    ~ObservableKeyedCollectionBase() {
-      Dispose(false);
-    }
-    protected virtual void Dispose(bool disposing) {
-      if (disposing) {
-        Clear();
-      }
-    }
-    public void Dispose() {
-      Dispose(true);
-      GC.SuppressFinalize(this);
     }
     #endregion
@@ -115,5 +100,5 @@
 
     #region Access
-    public bool Contains(TKey key) {
+    public bool ContainsKey(TKey key) {
       return dict.ContainsKey(key);
     }
@@ -203,4 +188,7 @@
 
     #region Conversion
+    public ReadOnlyObservableKeyedCollection<TKey, TItem> AsReadOnly() {
+      return new ReadOnlyObservableKeyedCollection<TKey, TItem>(this);
+    }
     public TItem[] ToArray() {
       return dict.Values.ToArray();
Index: trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs	(revision 2575)
+++ trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs	(revision 2618)
@@ -45,7 +45,4 @@
       get { return ((ICollection<T>)list).IsReadOnly; }
     }
-    bool ICollection<IndexedItem<T>>.IsReadOnly {
-      get { return ((ICollection<T>)list).IsReadOnly; }
-    }
 
     public T this[int index] {
@@ -74,19 +71,4 @@
     #endregion
 
-    #region Destructors
-    ~ObservableList() {
-      Dispose(false);
-    }
-    protected virtual void Dispose(bool disposing) {
-      if (disposing) {
-        Clear();
-      }
-    }
-    public void Dispose() {
-      Dispose(true);
-      GC.SuppressFinalize(this);
-    }
-    #endregion
-
     #region Access
     public List<T> GetRange(int index, int count) {
@@ -96,7 +78,4 @@
     public bool Contains(T item) {
       return list.Contains(item);
-    }
-    public bool Contains(IndexedItem<T> item) {
-      return list[item.Index].Equals(item.Value);
     }
 
@@ -170,8 +149,4 @@
       list.Add(item);
       OnItemsAdded(new IndexedItem<T>[] { new IndexedItem<T>(list.Count - 1, item) });
-    }
-    public void Add(IndexedItem<T> item) {
-      list.Insert(item.Index, item.Value);
-      OnItemsAdded(new IndexedItem<T>[] { item });
     }
     public void AddRange(IEnumerable<T> collection) {
@@ -209,12 +184,4 @@
       return false;
     }
-    public bool Remove(IndexedItem<T> item) {
-      if (list[item.Index].Equals(item.Value)) {
-        list.RemoveAt(item.Index);
-        OnItemsRemoved(new IndexedItem<T>[] { item });
-        return true;
-      }
-      return false;
-    }
     public int RemoveAll(Predicate<T> match) {
       if (match == null) throw new ArgumentNullException();
@@ -279,6 +246,6 @@
 
     #region Conversion
-    public ReadOnlyCollection<T> AsReadOnly() {
-      return list.AsReadOnly();
+    public ReadOnlyObservableList<T> AsReadOnly() {
+      return new ReadOnlyObservableList<T>(this);
     }
     public T[] ToArray() {
@@ -287,8 +254,4 @@
     void ICollection<T>.CopyTo(T[] array, int arrayIndex) {
       list.CopyTo(array, arrayIndex);
-    }
-    void ICollection<IndexedItem<T>>.CopyTo(IndexedItem<T>[] array, int arrayIndex) {
-      IndexedItem<T>[] items = GetIndexedItems();
-      items.CopyTo(array, arrayIndex);
     }
     public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) {
@@ -312,11 +275,4 @@
     IEnumerator<T> IEnumerable<T>.GetEnumerator() {
       return ((IEnumerable<T>)list).GetEnumerator();
-    }
-    IEnumerator<IndexedItem<T>> IEnumerable<IndexedItem<T>>.GetEnumerator() {
-      int index = -1;
-      foreach (T item in list) {
-        index++;
-        yield return new IndexedItem<T>(index, item);
-      }
     }
     IEnumerator IEnumerable.GetEnumerator() {
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableCollection.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableCollection.cs	(revision 2618)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableCollection.cs	(revision 2618)
@@ -0,0 +1,123 @@
+﻿#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.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Collections {
+  [Serializable]
+  public class ReadOnlyObservableCollection<T> : IObservableCollection<T> {
+    [Storable]
+    private IObservableCollection<T> collection;
+
+    #region Properties
+    public int Count {
+      get { return collection.Count; }
+    }
+    bool ICollection<T>.IsReadOnly {
+      get { return true; }
+    }
+    #endregion
+
+    #region Constructors
+    public ReadOnlyObservableCollection(IObservableCollection<T> collection) {
+      if (collection == null) throw new ArgumentNullException();
+      this.collection = collection;
+      collection.ItemsAdded += new CollectionItemsChangedEventHandler<T>(collection_ItemsAdded);
+      collection.ItemsRemoved += new CollectionItemsChangedEventHandler<T>(collection_ItemsRemoved);
+      collection.CollectionReset += new CollectionItemsChangedEventHandler<T>(collection_CollectionReset);
+    }
+    #endregion
+
+    #region Access
+    public bool Contains(T item) {
+      return collection.Contains(item);
+    }
+    #endregion
+
+    #region Manipulation
+    void ICollection<T>.Add(T item) {
+      throw new NotSupportedException();
+    }
+
+    bool ICollection<T>.Remove(T item) {
+      throw new NotSupportedException();
+    }
+
+    void ICollection<T>.Clear() {
+      throw new NotSupportedException();
+    }
+    #endregion
+
+    #region Conversion
+    public void CopyTo(T[] array, int arrayIndex) {
+      collection.CopyTo(array, arrayIndex);
+    }
+    #endregion
+
+    #region Enumeration
+    public IEnumerator<T> GetEnumerator() {
+      return ((IEnumerable<T>)collection).GetEnumerator();
+    }
+    IEnumerator IEnumerable.GetEnumerator() {
+      return ((IEnumerable)collection).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));
+    }
+
+    private void collection_ItemsAdded(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnItemsAdded(e.Items);
+    }
+    private void collection_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnItemsRemoved(e.Items);
+    }
+    private void collection_CollectionReset(object sender, CollectionItemsChangedEventArgs<T> e) {
+      OnCollectionReset(e.Items, e.OldItems);
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableDictionary.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableDictionary.cs	(revision 2618)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableDictionary.cs	(revision 2618)
@@ -0,0 +1,161 @@
+﻿#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.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System.Runtime.Serialization;
+
+namespace HeuristicLab.Collections {
+  [Serializable]
+  public class ReadOnlyObservableDictionary<TKey, TValue> : IObservableDictionary<TKey, TValue> {
+    [Storable]
+    private IObservableDictionary<TKey, TValue> dict;
+
+    #region Properties
+    public ICollection<TKey> Keys {
+      get { return dict.Keys; }
+    }
+    public ICollection<TValue> Values {
+      get { return dict.Values; }
+    }
+    public int Count {
+      get { return dict.Count; }
+    }
+    bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
+      get { return true; }
+    }
+
+    public TValue this[TKey key] {
+      get { return dict[key]; }
+    }
+    TValue IDictionary<TKey, TValue>.this[TKey key] {
+      get { return dict[key]; }
+      set { throw new NotSupportedException(); }
+    }
+    #endregion
+
+    #region Constructors
+    public ReadOnlyObservableDictionary(IObservableDictionary<TKey, TValue> dictionary) {
+      if (dictionary == null) throw new ArgumentNullException();
+      dict = dictionary;
+      dict.ItemsAdded += new CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>>(dict_ItemsAdded);
+      dict.ItemsRemoved += new CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>>(dict_ItemsRemoved);
+      dict.ItemsReplaced += new CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>>(dict_ItemsReplaced);
+      dict.CollectionReset += new CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>>(dict_CollectionReset);
+    }
+    #endregion
+
+    #region Access
+    public bool ContainsKey(TKey key) {
+      return dict.ContainsKey(key);
+    }
+    bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) {
+      return dict.Contains(item);
+    }
+
+    public bool TryGetValue(TKey key, out TValue value) {
+      return dict.TryGetValue(key, out value);
+    }
+    #endregion
+
+    #region Manipulation
+    void IDictionary<TKey, TValue>.Add(TKey key, TValue value) {
+      throw new NotSupportedException();
+    }
+    void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) {
+      throw new NotSupportedException();
+    }
+
+    bool IDictionary<TKey, TValue>.Remove(TKey key) {
+      throw new NotSupportedException();
+    }
+    bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) {
+      throw new NotSupportedException();
+    }
+
+    void ICollection<KeyValuePair<TKey, TValue>>.Clear() {
+      throw new NotSupportedException();
+    }
+    #endregion
+
+    #region Conversion
+    void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
+      ((ICollection<KeyValuePair<TKey, TValue>>)dict).CopyTo(array, arrayIndex);
+    }
+    #endregion
+
+    #region Enumeration
+    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
+      return dict.GetEnumerator();
+    }
+    IEnumerator IEnumerable.GetEnumerator() {
+      return ((IEnumerable)dict).GetEnumerator();
+    }
+    #endregion
+
+    #region Events
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsAdded;
+    protected virtual void OnItemsAdded(IEnumerable<KeyValuePair<TKey, TValue>> items) {
+      if (ItemsAdded != null)
+        ItemsAdded(this, new CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsRemoved;
+    protected virtual void OnItemsRemoved(IEnumerable<KeyValuePair<TKey, TValue>> items) {
+      if (ItemsRemoved != null)
+        ItemsRemoved(this, new CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> ItemsReplaced;
+    protected virtual void OnItemsReplaced(IEnumerable<KeyValuePair<TKey, TValue>> items, IEnumerable<KeyValuePair<TKey, TValue>> oldItems) {
+      if (ItemsReplaced != null)
+        ItemsReplaced(this, new CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<KeyValuePair<TKey, TValue>> CollectionReset;
+    protected virtual void OnCollectionReset(IEnumerable<KeyValuePair<TKey, TValue>> items, IEnumerable<KeyValuePair<TKey, TValue>> oldItems) {
+      if (CollectionReset != null)
+        CollectionReset(this, new CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>>(items, oldItems));
+    }
+
+    private void dict_ItemsAdded(object sender, CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>> e) {
+      OnItemsAdded(e.Items);
+    }
+    private void dict_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>> e) {
+      OnItemsRemoved(e.Items);
+    }
+    private void dict_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>> e) {
+      OnItemsReplaced(e.Items, e.OldItems);
+    }
+    private void dict_CollectionReset(object sender, CollectionItemsChangedEventArgs<KeyValuePair<TKey, TValue>> e) {
+      OnCollectionReset(e.Items, e.OldItems);
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableKeyedCollection.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableKeyedCollection.cs	(revision 2618)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableKeyedCollection.cs	(revision 2618)
@@ -0,0 +1,147 @@
+﻿#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.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Collections {
+  [Serializable]
+  public class ReadOnlyObservableKeyedCollection<TKey, TItem> : IObservableKeyedCollection<TKey, TItem> {
+    [Storable]
+    private IObservableKeyedCollection<TKey, TItem> collection;
+
+    #region Properties
+    public int Count {
+      get { return collection.Count; }
+    }
+    bool ICollection<TItem>.IsReadOnly {
+      get { return true; }
+    }
+
+    public TItem this[TKey key] {
+      get {
+        return collection[key];
+      }
+    }
+    #endregion
+
+    #region Constructors
+    public ReadOnlyObservableKeyedCollection(IObservableKeyedCollection<TKey, TItem> collection) {
+      if (collection == null) throw new ArgumentNullException();
+      this.collection = collection;
+      collection.ItemsAdded += new CollectionItemsChangedEventHandler<TItem>(collection_ItemsAdded);
+      collection.ItemsRemoved += new CollectionItemsChangedEventHandler<TItem>(collection_ItemsRemoved);
+      collection.ItemsReplaced += new CollectionItemsChangedEventHandler<TItem>(collection_ItemsReplaced);
+      collection.CollectionReset += new CollectionItemsChangedEventHandler<TItem>(collection_CollectionReset);
+    }
+    #endregion
+
+    #region Access
+    public bool ContainsKey(TKey key) {
+      return collection.ContainsKey(key);
+    }
+    public bool Contains(TItem item) {
+      return collection.Contains(item);
+    }
+
+    public bool TryGetValue(TKey key, out TItem item) {
+      return collection.TryGetValue(key, out item);
+    }
+    #endregion
+
+    #region Manipulation
+    void ICollection<TItem>.Add(TItem item) {
+      throw new NotSupportedException();
+    }
+
+    bool ICollection<TItem>.Remove(TItem item) {
+      throw new NotSupportedException();
+    }
+
+    void ICollection<TItem>.Clear() {
+      throw new NotSupportedException();
+    }
+    #endregion
+
+    #region Conversion
+    public void CopyTo(TItem[] array, int arrayIndex) {
+      collection.CopyTo(array, arrayIndex);
+    }
+    #endregion
+
+    #region Enumeration
+    public IEnumerator<TItem> GetEnumerator() {
+      return ((IEnumerable<TItem>)collection).GetEnumerator();
+    }
+    IEnumerator IEnumerable.GetEnumerator() {
+      return ((IEnumerable)collection).GetEnumerator();
+    }
+    #endregion
+
+    #region Events
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<TItem> ItemsAdded;
+    protected virtual void OnItemsAdded(IEnumerable<TItem> items) {
+      if (ItemsAdded != null)
+        ItemsAdded(this, new CollectionItemsChangedEventArgs<TItem>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<TItem> ItemsRemoved;
+    protected virtual void OnItemsRemoved(IEnumerable<TItem> items) {
+      if (ItemsRemoved != null)
+        ItemsRemoved(this, new CollectionItemsChangedEventArgs<TItem>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<TItem> ItemsReplaced;
+    protected virtual void OnItemsReplaced(IEnumerable<TItem> items, IEnumerable<TItem> oldItems) {
+      if (ItemsReplaced != null)
+        ItemsReplaced(this, new CollectionItemsChangedEventArgs<TItem>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<TItem> CollectionReset;
+    protected virtual void OnCollectionReset(IEnumerable<TItem> items, IEnumerable<TItem> oldItems) {
+      if (CollectionReset != null)
+        CollectionReset(this, new CollectionItemsChangedEventArgs<TItem>(items, oldItems));
+    }
+
+    private void collection_ItemsAdded(object sender, CollectionItemsChangedEventArgs<TItem> e) {
+      OnItemsAdded(e.Items);
+    }
+    private void collection_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<TItem> e) {
+      OnItemsRemoved(e.Items);
+    }
+    private void collection_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<TItem> e) {
+      OnItemsReplaced(e.Items, e.OldItems);
+    }
+    private void collection_CollectionReset(object sender, CollectionItemsChangedEventArgs<TItem> e) {
+      OnCollectionReset(e.Items, e.OldItems);
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableList.cs
===================================================================
--- trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableList.cs	(revision 2618)
+++ trunk/sources/HeuristicLab.Collections/3.3/ReadOnlyObservableList.cs	(revision 2618)
@@ -0,0 +1,164 @@
+﻿#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.Linq;
+using System.Text;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Collections {
+  [Serializable]
+  public class ReadOnlyObservableList<T> : IObservableList<T> {
+    [Storable]
+    private IObservableList<T> list;
+
+    #region Properties
+    public int Count {
+      get { return ((ICollection<T>)list).Count; }
+    }
+    bool ICollection<T>.IsReadOnly {
+      get { return true; }
+    }
+
+    public T this[int index] {
+      get { return list[index]; }
+    }
+    T IList<T>.this[int index] {
+      get { return list[index]; }
+      set { throw new NotSupportedException(); }
+    }
+    #endregion
+
+    #region Constructors
+    public ReadOnlyObservableList(IObservableList<T> list) {
+      if (list == null) throw new ArgumentNullException();
+      this.list = list;
+      list.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<T>>(list_ItemsAdded);
+      list.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<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);
+    }
+    #endregion
+
+    #region Access
+    public bool Contains(T item) {
+      return list.Contains(item);
+    }
+
+    public int IndexOf(T item) {
+      return list.IndexOf(item);
+    }
+    #endregion
+
+    #region Manipulation
+    void ICollection<T>.Add(T item) {
+      throw new NotSupportedException();
+    }
+
+    void IList<T>.Insert(int index, T item) {
+      throw new NotSupportedException();
+    }
+
+    bool ICollection<T>.Remove(T item) {
+      throw new NotSupportedException();
+    }
+    void IList<T>.RemoveAt(int index) {
+      throw new NotSupportedException();
+    }
+
+    void ICollection<T>.Clear() {
+      throw new NotSupportedException();
+    }
+    #endregion
+
+    #region Conversion
+    void ICollection<T>.CopyTo(T[] array, int arrayIndex) {
+      list.CopyTo(array, arrayIndex);
+    }
+    #endregion
+
+    #region Enumeration
+    public IEnumerator<T> GetEnumerator() {
+      return ((ICollection<T>)list).GetEnumerator();
+    }
+    IEnumerator IEnumerable.GetEnumerator() {
+      return ((IEnumerable)list).GetEnumerator();
+    }
+    #endregion
+
+    #region Events
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsAdded;
+    protected virtual void OnItemsAdded(IEnumerable<IndexedItem<T>> items) {
+      if (ItemsAdded != null)
+        ItemsAdded(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsRemoved;
+    protected virtual void OnItemsRemoved(IEnumerable<IndexedItem<T>> items) {
+      if (ItemsRemoved != null)
+        ItemsRemoved(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsReplaced;
+    protected virtual void OnItemsReplaced(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
+      if (ItemsReplaced != null)
+        ItemsReplaced(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<IndexedItem<T>> ItemsMoved;
+    protected virtual void OnItemsMoved(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
+      if (ItemsMoved != null)
+        ItemsMoved(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
+    }
+
+    [field: NonSerialized]
+    public event CollectionItemsChangedEventHandler<IndexedItem<T>> CollectionReset;
+    protected virtual void OnCollectionReset(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
+      if (CollectionReset != null)
+        CollectionReset(this, new CollectionItemsChangedEventArgs<IndexedItem<T>>(items, oldItems));
+    }
+
+    private void list_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      OnItemsAdded(e.Items);
+    }
+    private void list_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      OnItemsRemoved(e.Items);
+    }
+    private void list_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      OnItemsReplaced(e.Items, e.OldItems);
+    }
+    private void list_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      OnItemsMoved(e.Items, e.OldItems);
+    }
+    private void list_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      OnCollectionReset(e.Items, e.OldItems);
+    }
+    #endregion
+  }
+}
