Index: /trunk/sources/HeuristicLab.Core.Views/3.3/HeuristicLab.Core.Views-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Core.Views/3.3/HeuristicLab.Core.Views-3.3.csproj	(revision 2745)
+++ /trunk/sources/HeuristicLab.Core.Views/3.3/HeuristicLab.Core.Views-3.3.csproj	(revision 2746)
@@ -52,4 +52,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ItemArrayView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ItemArrayView.Designer.cs">
+      <DependentUpon>ItemArrayView.cs</DependentUpon>
+    </Compile>
     <Compile Include="CreateParameterDialog.cs">
       <SubType>Form</SubType>
Index: /trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.Designer.cs	(revision 2746)
+++ /trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.Designer.cs	(revision 2746)
@@ -0,0 +1,212 @@
+#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.Windows.Forms;
+
+namespace HeuristicLab.Core.Views {
+  partial class ItemArrayView<T> {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing) {
+        foreach (ListViewItem listViewItem in itemsListView.Items) {
+          T item = listViewItem.Tag as T;
+          if (item != null) item.Changed -= new ChangedEventHandler(Item_Changed);
+        }
+        if (components != null) components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.moveUpButton = new System.Windows.Forms.Button();
+      this.moveDownButton = new System.Windows.Forms.Button();
+      this.itemsListView = new System.Windows.Forms.ListView();
+      this.listViewColumnHeader = new System.Windows.Forms.ColumnHeader();
+      this.imageList = new System.Windows.Forms.ImageList(this.components);
+      this.detailsGroupBox = new System.Windows.Forms.GroupBox();
+      this.viewHost = new HeuristicLab.Core.Views.ViewHost();
+      this.itemsGroupBox = new System.Windows.Forms.GroupBox();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.detailsGroupBox.SuspendLayout();
+      this.itemsGroupBox.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+      this.splitContainer.Location = new System.Drawing.Point(3, 16);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.moveUpButton);
+      this.splitContainer.Panel1.Controls.Add(this.moveDownButton);
+      this.splitContainer.Panel1.Controls.Add(this.itemsListView);
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.detailsGroupBox);
+      this.splitContainer.Size = new System.Drawing.Size(493, 323);
+      this.splitContainer.SplitterDistance = 200;
+      this.splitContainer.TabIndex = 0;
+      // 
+      // moveUpButton
+      // 
+      this.moveUpButton.Enabled = false;
+      this.moveUpButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.ArrowUp;
+      this.moveUpButton.Location = new System.Drawing.Point(3, 3);
+      this.moveUpButton.Name = "moveUpButton";
+      this.moveUpButton.Size = new System.Drawing.Size(23, 23);
+      this.moveUpButton.TabIndex = 0;
+      this.toolTip.SetToolTip(this.moveUpButton, "Move Up");
+      this.moveUpButton.UseVisualStyleBackColor = true;
+      this.moveUpButton.Click += new System.EventHandler(this.moveUpButton_Click);
+      // 
+      // moveDownButton
+      // 
+      this.moveDownButton.Enabled = false;
+      this.moveDownButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.ArrowDown;
+      this.moveDownButton.Location = new System.Drawing.Point(32, 3);
+      this.moveDownButton.Name = "moveDownButton";
+      this.moveDownButton.Size = new System.Drawing.Size(23, 23);
+      this.moveDownButton.TabIndex = 1;
+      this.toolTip.SetToolTip(this.moveDownButton, "Move Down");
+      this.moveDownButton.UseVisualStyleBackColor = true;
+      this.moveDownButton.Click += new System.EventHandler(this.moveDownButton_Click);
+      // 
+      // itemsListView
+      // 
+      this.itemsListView.AllowDrop = true;
+      this.itemsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.itemsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.listViewColumnHeader});
+      this.itemsListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
+      this.itemsListView.HideSelection = false;
+      this.itemsListView.Location = new System.Drawing.Point(3, 32);
+      this.itemsListView.Name = "itemsListView";
+      this.itemsListView.ShowItemToolTips = true;
+      this.itemsListView.Size = new System.Drawing.Size(194, 287);
+      this.itemsListView.SmallImageList = this.imageList;
+      this.itemsListView.TabIndex = 2;
+      this.itemsListView.UseCompatibleStateImageBehavior = false;
+      this.itemsListView.View = System.Windows.Forms.View.Details;
+      this.itemsListView.SelectedIndexChanged += new System.EventHandler(this.itemsListView_SelectedIndexChanged);
+      this.itemsListView.SizeChanged += new System.EventHandler(this.itemsListView_SizeChanged);
+      this.itemsListView.DoubleClick += new System.EventHandler(this.itemsListView_DoubleClick);
+      this.itemsListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.itemsListView_DragDrop);
+      this.itemsListView.DragEnter += new System.Windows.Forms.DragEventHandler(this.itemsListView_DragEnterOver);
+      this.itemsListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.itemsListView_KeyDown);
+      this.itemsListView.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.itemsListView_ItemDrag);
+      this.itemsListView.DragOver += new System.Windows.Forms.DragEventHandler(this.itemsListView_DragEnterOver);
+      // 
+      // imageList
+      // 
+      this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+      this.imageList.ImageSize = new System.Drawing.Size(16, 16);
+      this.imageList.TransparentColor = System.Drawing.Color.Transparent;
+      // 
+      // detailsGroupBox
+      // 
+      this.detailsGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.detailsGroupBox.Controls.Add(this.viewHost);
+      this.detailsGroupBox.Location = new System.Drawing.Point(3, 26);
+      this.detailsGroupBox.Name = "detailsGroupBox";
+      this.detailsGroupBox.Size = new System.Drawing.Size(283, 294);
+      this.detailsGroupBox.TabIndex = 0;
+      this.detailsGroupBox.TabStop = false;
+      this.detailsGroupBox.Text = "&Details";
+      // 
+      // viewHost
+      // 
+      this.viewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.viewHost.Content = null;
+      this.viewHost.Location = new System.Drawing.Point(6, 19);
+      this.viewHost.Name = "viewHost";
+      this.viewHost.Size = new System.Drawing.Size(271, 269);
+      this.viewHost.TabIndex = 0;
+      // 
+      // itemsGroupBox
+      // 
+      this.itemsGroupBox.Controls.Add(this.splitContainer);
+      this.itemsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.itemsGroupBox.Location = new System.Drawing.Point(0, 0);
+      this.itemsGroupBox.Name = "itemsGroupBox";
+      this.itemsGroupBox.Size = new System.Drawing.Size(499, 342);
+      this.itemsGroupBox.TabIndex = 0;
+      this.itemsGroupBox.TabStop = false;
+      this.itemsGroupBox.Text = "&Items";
+      // 
+      // ItemArrayView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.Controls.Add(this.itemsGroupBox);
+      this.Name = "ItemArrayView";
+      this.Size = new System.Drawing.Size(499, 342);
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      this.splitContainer.ResumeLayout(false);
+      this.detailsGroupBox.ResumeLayout(false);
+      this.itemsGroupBox.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    protected System.Windows.Forms.SplitContainer splitContainer;
+    protected System.Windows.Forms.ColumnHeader listViewColumnHeader;
+    protected GroupBox itemsGroupBox;
+    protected ListView itemsListView;
+    protected GroupBox detailsGroupBox;
+    protected Button moveUpButton;
+    protected Button moveDownButton;
+    protected ToolTip toolTip;
+    protected ImageList imageList;
+    protected ViewHost viewHost;
+  }
+}
Index: /trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.cs	(revision 2746)
+++ /trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.cs	(revision 2746)
@@ -0,0 +1,327 @@
+#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.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Core.Views {
+  /// <summary>
+  /// The visual representation of all variables in a specified scope.
+  /// </summary>
+  [Content(typeof(ItemArray<>), true)]
+  [Content(typeof(IObservableArray<>), false)]
+  public partial class ItemArrayView<T> : ContentView where T : class, IItem {
+    /// <summary>
+    /// Gets or sets the scope whose variables to represent visually.
+    /// </summary>
+    /// <remarks>Uses property <see cref="ViewBase.Item"/> of base class <see cref="ViewBase"/>.
+    /// No won data storage present.</remarks>
+    public new IObservableArray<T> Content {
+      get { return (IObservableArray<T>)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public ListView ItemsListView {
+      get { return itemsListView; }
+    }
+
+    /// <summary>
+    /// Initializes a new instance of <see cref="VariablesScopeView"/> with caption "Variables Scope View".
+    /// </summary>
+    public ItemArrayView() {
+      InitializeComponent();
+      Caption = "Item Array";
+    }
+    public ItemArrayView(IObservableArray<T> content)
+      : this() {
+      Content = content;
+    }
+
+    /// <summary>
+    /// Removes the eventhandlers from the underlying <see cref="IScope"/>.
+    /// </summary>
+    /// <remarks>Calls <see cref="ViewBase.RemoveItemEvents"/> of base class <see cref="ViewBase"/>.</remarks>
+    protected override void DeregisterContentEvents() {
+      Content.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsReplaced);
+      Content.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsMoved);
+      Content.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_CollectionReset);
+      base.DeregisterContentEvents();
+    }
+
+    /// <summary>
+    /// Adds eventhandlers to the underlying <see cref="IScope"/>.
+    /// </summary>
+    /// <remarks>Calls <see cref="ViewBase.AddItemEvents"/> of base class <see cref="ViewBase"/>.</remarks>
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsReplaced);
+      Content.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsMoved);
+      Content.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_CollectionReset);
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      Caption = "Item Array";
+      while (itemsListView.Items.Count > 0) RemoveListViewItem(itemsListView.Items[0]);
+      itemsListView.Enabled = false;
+      detailsGroupBox.Enabled = false;
+      viewHost.Content = null;
+      moveUpButton.Enabled = false;
+      moveDownButton.Enabled = false;
+
+      if (Content != null) {
+        Caption += " (" + Content.GetType().Name + ")";
+        itemsListView.Enabled = true;
+        foreach (T item in Content)
+          AddListViewItem(CreateListViewItem(item));
+      }
+    }
+
+    protected virtual T CreateItem() {
+      try {
+        return (T)Activator.CreateInstance(typeof(T));
+      }
+      catch (Exception ex) {
+        Auxiliary.ShowErrorMessageBox(ex);
+        return null;
+      }
+    }
+    protected virtual ListViewItem CreateListViewItem(T item) {
+      if (item == null) {
+        return new ListViewItem("null");
+      } else {
+        if (!itemsListView.SmallImageList.Images.ContainsKey(item.GetType().FullName))
+          itemsListView.SmallImageList.Images.Add(item.GetType().FullName, item.ItemImage);
+
+        ListViewItem listViewItem = new ListViewItem();
+        listViewItem.Text = item.ToString();
+        listViewItem.ToolTipText = item.ItemName + ": " + item.ItemDescription;
+        listViewItem.ImageIndex = itemsListView.SmallImageList.Images.IndexOfKey(item.GetType().FullName);
+        listViewItem.Tag = item;
+        return listViewItem;
+      }
+    }
+    protected virtual void AddListViewItem(ListViewItem listViewItem) {
+      itemsListView.Items.Add(listViewItem);
+      if (listViewItem.Tag != null)
+        ((T)listViewItem.Tag).Changed += new ChangedEventHandler(Item_Changed);
+    }
+    protected virtual void InsertListViewItem(int index, ListViewItem listViewItem) {
+      itemsListView.Items.Insert(index, listViewItem);
+      if (listViewItem.Tag != null)
+        ((T)listViewItem.Tag).Changed += new ChangedEventHandler(Item_Changed);
+    }
+    protected virtual void RemoveListViewItem(ListViewItem listViewItem) {
+      if (listViewItem.Tag != null)
+        ((T)listViewItem.Tag).Changed -= new ChangedEventHandler(Item_Changed);
+      listViewItem.Remove();
+    }
+    protected virtual void UpdateListViewItem(ListViewItem listViewItem) {
+      T item = listViewItem.Tag as T;
+      if ((item != null) && (!itemsListView.SmallImageList.Images.ContainsKey(item.GetType().FullName)))
+        itemsListView.SmallImageList.Images.Add(item.GetType().FullName, item.ItemImage);
+
+      listViewItem.Text = item == null ? "null" : item.ToString();
+      listViewItem.ToolTipText = item == null ? string.Empty : item.ItemName + ": " + item.ItemDescription;
+      listViewItem.ImageIndex = item == null ? -1 : itemsListView.SmallImageList.Images.IndexOfKey(item.GetType().FullName);
+    }
+
+    protected virtual void itemsListView_SelectedIndexChanged(object sender, EventArgs e) {
+      moveUpButton.Enabled = itemsListView.SelectedItems.Count == 1 &&
+                             itemsListView.SelectedIndices[0] != 0 &&
+                             !Content.IsReadOnly;
+      moveDownButton.Enabled = itemsListView.SelectedItems.Count == 1 &&
+                               itemsListView.SelectedIndices[0] != itemsListView.Items.Count - 1 &&
+                               !Content.IsReadOnly;
+
+      if (itemsListView.SelectedItems.Count == 1) {
+        T item = itemsListView.SelectedItems[0].Tag as T;
+        viewHost.Content = item;
+        detailsGroupBox.Enabled = true;
+      } else {
+        viewHost.Content = null;
+        detailsGroupBox.Enabled = false;
+      }
+    }
+
+    #region ListView Events
+    protected virtual void itemsListView_SizeChanged(object sender, EventArgs e) {
+      if (itemsListView.Columns.Count > 0)
+        itemsListView.Columns[0].Width = Math.Max(0, itemsListView.Width - 25);
+    }
+
+    protected virtual void itemsListView_KeyDown(object sender, KeyEventArgs e) {
+      if (e.KeyCode == Keys.Delete) {
+        if ((itemsListView.SelectedItems.Count > 0) && !Content.IsReadOnly) {
+          foreach (ListViewItem item in itemsListView.SelectedItems)
+            Content[item.Index] = null;
+        }
+      }
+    }
+
+    protected virtual void itemsListView_DoubleClick(object sender, EventArgs e) {
+      if (itemsListView.SelectedItems.Count == 1) {
+        T item = itemsListView.SelectedItems[0].Tag as T;
+        if (item != null) {
+          IView view = MainFormManager.CreateDefaultView(item);
+          if (view != null) view.Show();
+        }
+      }
+    }
+
+    protected virtual void itemsListView_ItemDrag(object sender, ItemDragEventArgs e) {
+      ListViewItem listViewItem = (ListViewItem)e.Item;
+      T item = listViewItem.Tag as T;
+      if (item != null) {
+        DataObject data = new DataObject();
+        data.SetData("Type", item.GetType());
+        data.SetData("Value", item);
+        if (Content.IsReadOnly) {
+          DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
+        } else {
+          DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
+          if ((result & DragDropEffects.Move) == DragDropEffects.Move)
+            Content[listViewItem.Index] = null;
+        }
+      }
+    }
+    protected virtual void itemsListView_DragEnterOver(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.None;
+      Type type = e.Data.GetData("Type") as Type;
+      if ((!Content.IsReadOnly) && (type != null) && (typeof(T).IsAssignableFrom(type))) {
+        Point p = itemsListView.PointToClient(new Point(e.X, e.Y));
+        ListViewItem listViewItem = itemsListView.GetItemAt(p.X, p.Y);
+        if (listViewItem != null) {
+          if ((e.KeyState & 8) == 8) e.Effect = DragDropEffects.Copy;  // CTRL key
+          else if ((e.KeyState & 4) == 4) e.Effect = DragDropEffects.Move;  // SHIFT key
+          else if ((e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) e.Effect = DragDropEffects.Link;
+          else if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy;
+          else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move;
+        }
+      }
+    }
+    protected virtual void itemsListView_DragDrop(object sender, DragEventArgs e) {
+      if (e.Effect != DragDropEffects.None) {
+        T item = e.Data.GetData("Value") as T;
+        if ((e.Effect & DragDropEffects.Copy) == DragDropEffects.Copy) item = (T)item.Clone();
+
+        Point p = itemsListView.PointToClient(new Point(e.X, e.Y));
+        ListViewItem listViewItem = itemsListView.GetItemAt(p.X, p.Y);
+        Content[listViewItem.Index] = item;
+      }
+    }
+    #endregion
+
+    #region Button Events
+    protected virtual void moveUpButton_Click(object sender, EventArgs e) {
+      if (itemsListView.SelectedItems.Count == 1) {
+        int index = itemsListView.SelectedIndices[0];
+        T item = Content[index - 1];
+        Content[index - 1] = Content[index];
+        itemsListView.Items[index].Selected = false;
+        itemsListView.Items[index - 1].Selected = true;
+        Content[index] = item;
+      }
+    }
+    protected virtual void moveDownButton_Click(object sender, EventArgs e) {
+      if (itemsListView.SelectedItems.Count == 1) {
+        int index = itemsListView.SelectedIndices[0];
+        T item = Content[index + 1];
+        Content[index + 1] = Content[index];
+        itemsListView.Items[index].Selected = false;
+        itemsListView.Items[index + 1].Selected = true;
+        Content[index] = item;
+      }
+    }
+    #endregion
+
+    #region Content Events
+    protected virtual void Content_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsReplaced), sender, e);
+      else {
+        int[] selected = new int[itemsListView.SelectedIndices.Count];
+        itemsListView.SelectedIndices.CopyTo(selected, 0);
+
+        List<ListViewItem> listViewItems = new List<ListViewItem>();
+        foreach (IndexedItem<T> item in e.OldItems)
+          listViewItems.Add(itemsListView.Items[item.Index]);
+        foreach (ListViewItem listViewItem in listViewItems)
+          RemoveListViewItem(listViewItem);
+
+        foreach (IndexedItem<T> item in e.Items)
+          InsertListViewItem(item.Index, CreateListViewItem(item.Value));
+
+        for (int i = 0; i < selected.Length; i++)
+          itemsListView.Items[selected[i]].Selected = true;
+      }
+    }
+    protected virtual void Content_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsMoved), sender, e);
+      else {
+        foreach (IndexedItem<T> item in e.Items) {
+          ListViewItem listViewItem = itemsListView.Items[item.Index];
+          listViewItem.Tag = item.Value;
+          UpdateListViewItem(listViewItem);
+        }
+      }
+    }
+    protected virtual void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_CollectionReset), sender, e);
+      else {
+        List<ListViewItem> listViewItems = new List<ListViewItem>();
+        foreach (IndexedItem<T> item in e.OldItems)
+          listViewItems.Add(itemsListView.Items[item.Index]);
+        foreach (ListViewItem listViewItem in listViewItems)
+          RemoveListViewItem(listViewItem);
+
+        foreach (IndexedItem<T> item in e.Items)
+          InsertListViewItem(item.Index, CreateListViewItem(item.Value));
+      }
+    }
+    #endregion
+
+    #region Item Events
+    protected virtual void Item_Changed(object sender, ChangedEventArgs e) {
+      if (InvokeRequired)
+        Invoke(new ChangedEventHandler(Item_Changed), sender, e);
+      else {
+        T item = (T)sender;
+        foreach (ListViewItem listViewItem in itemsListView.Items) {
+          if (((T)listViewItem.Tag) == item)
+            UpdateListViewItem(listViewItem);
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Core/3.3/HeuristicLab.Core-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Core/3.3/HeuristicLab.Core-3.3.csproj	(revision 2745)
+++ /trunk/sources/HeuristicLab.Core/3.3/HeuristicLab.Core-3.3.csproj	(revision 2746)
@@ -103,4 +103,5 @@
     <Compile Include="Attributes\CreatableAttribute.cs" />
     <Compile Include="ChangedEventArgs.cs" />
+    <Compile Include="ItemArray.cs" />
     <Compile Include="DeepCloneable.cs" />
     <Compile Include="Engine.cs" />
Index: /trunk/sources/HeuristicLab.Core/3.3/ItemArray.cs
===================================================================
--- /trunk/sources/HeuristicLab.Core/3.3/ItemArray.cs	(revision 2746)
+++ /trunk/sources/HeuristicLab.Core/3.3/ItemArray.cs	(revision 2746)
@@ -0,0 +1,110 @@
+#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.Text;
+using System.Drawing;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common.Resources;
+using HeuristicLab.Collections;
+
+
+namespace HeuristicLab.Core {
+  [EmptyStorableClass]
+  [Item("ItemArray<T>", "Represents an array of items.")]
+  public class ItemArray<T> : ObservableArray<T>, IItem where T : class, IItem {
+    [Storable(Name = "RestoreEvents")]
+    private object RestoreEvents {
+      get { return null; }
+      set {
+        foreach (T item in this)
+          if (item != null) item.Changed += new ChangedEventHandler(Item_Changed);
+      }
+    }
+
+    public virtual string ItemName {
+      get { return ItemAttribute.GetName(this.GetType()); }
+    }
+    public virtual string ItemDescription {
+      get { return ItemAttribute.GetDescription(this.GetType()); }
+    }
+    public virtual Image ItemImage {
+      get { return VS2008ImageLibrary.Class; }
+    }
+
+    public ItemArray() : base() { }
+    public ItemArray(int length) : base(length) { }
+    public ItemArray(T[] array) : base(array) { }
+    public ItemArray(IEnumerable<T> collection) : base(collection) { }
+
+    public object Clone() {
+      return Clone(new Cloner());
+    }
+
+    public IDeepCloneable Clone(Cloner cloner) {
+      T[] items = new T[Length];
+      for (int i = 0; i < items.Length; i++)
+        items[i] = (T)cloner.Clone(this[i]);
+      ItemArray<T> clone = (ItemArray<T>)Activator.CreateInstance(this.GetType(), new object[] { items });
+      cloner.RegisterClonedObject(this, clone);
+      return clone;
+    }
+
+    public override string ToString() {
+      return ItemName;
+    }
+
+    public event ChangedEventHandler Changed;
+    protected void OnChanged() {
+      OnChanged(new ChangedEventArgs());
+    }
+    protected virtual void OnChanged(ChangedEventArgs e) {
+      if ((e.RegisterChangedObject(this)) && (Changed != null))
+        Changed(this, e);
+    }
+
+    protected override void OnItemsReplaced(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
+      foreach (IndexedItem<T> oldItem in oldItems)
+        if (oldItem.Value != null) oldItem.Value.Changed -= new ChangedEventHandler(Item_Changed);
+      foreach (IndexedItem<T> item in items)
+        if (item.Value != null) item.Value.Changed += new ChangedEventHandler(Item_Changed);
+      base.OnItemsReplaced(items, oldItems);
+    }
+    protected override void OnCollectionReset(IEnumerable<IndexedItem<T>> items, IEnumerable<IndexedItem<T>> oldItems) {
+      foreach (IndexedItem<T> oldItem in oldItems)
+        if (oldItem.Value != null) oldItem.Value.Changed -= new ChangedEventHandler(Item_Changed);
+      foreach (IndexedItem<T> item in items)
+        if (item.Value != null) item.Value.Changed += new ChangedEventHandler(Item_Changed);
+      base.OnCollectionReset(items, oldItems);
+    }
+    protected override void OnPropertyChanged(string propertyName) {
+      base.OnPropertyChanged(propertyName);
+      OnChanged();
+    }
+
+    private void Item_Changed(object sender, ChangedEventArgs e) {
+      OnChanged(e);
+    }
+  }
+}
