Index: trunk/sources/HeuristicLab.Core/HeuristicLab.Core.csproj
===================================================================
--- trunk/sources/HeuristicLab.Core/HeuristicLab.Core.csproj	(revision 186)
+++ trunk/sources/HeuristicLab.Core/HeuristicLab.Core.csproj	(revision 187)
@@ -92,4 +92,5 @@
     </Compile>
     <Compile Include="AliasEventArgs.cs" />
+    <Compile Include="KeyValueEventArgs.cs" />
     <Compile Include="OperatorBaseDescriptionView.cs">
       <SubType>UserControl</SubType>
Index: trunk/sources/HeuristicLab.Core/KeyValueEventArgs.cs
===================================================================
--- trunk/sources/HeuristicLab.Core/KeyValueEventArgs.cs	(revision 187)
+++ trunk/sources/HeuristicLab.Core/KeyValueEventArgs.cs	(revision 187)
@@ -0,0 +1,23 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace HeuristicLab.Core {
+  public class KeyValueEventArgs : EventArgs {
+
+    private IItem key;
+    public IItem Key {
+      get { return key; }
+    }
+
+    private IItem value;
+    public IItem Value {
+      get { return value; }
+    }
+
+    public KeyValueEventArgs(IItem key, IItem value) {
+      this.key = key;
+      this.value = value; 
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Data/EditKeyValueDialog.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/EditKeyValueDialog.cs	(revision 187)
+++ trunk/sources/HeuristicLab.Data/EditKeyValueDialog.cs	(revision 187)
@@ -0,0 +1,33 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core; 
+
+namespace HeuristicLab.Data {
+  public partial class EditKeyValueDialog : Form {
+    private IItem key; 
+    public IItem Key {
+      get { return key; }
+    }
+
+    private IItem value;
+    public IItem Value {
+      get { return value; }
+    }
+
+    public EditKeyValueDialog(Type keyType, Type valueType) {
+      InitializeComponent();
+      key = (IItem) Activator.CreateInstance(keyType);
+      value = (IItem) Activator.CreateInstance(valueType); 
+      keyPanel.Controls.Add((Control) key.CreateView());
+      valuePanel.Controls.Add((Control) value.CreateView()); 
+    }
+
+    private void okButton_Click(object sender, EventArgs e) {
+      this.DialogResult = DialogResult.OK;
+      this.Close();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Data/EditKeyValueDialog.designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/EditKeyValueDialog.designer.cs	(revision 187)
+++ trunk/sources/HeuristicLab.Data/EditKeyValueDialog.designer.cs	(revision 187)
@@ -0,0 +1,131 @@
+﻿namespace HeuristicLab.Data {
+  partial class EditKeyValueDialog {
+    /// <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 && (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.okButton = new System.Windows.Forms.Button();
+      this.cancelButton = new System.Windows.Forms.Button();
+      this.keyPanel = new System.Windows.Forms.Panel();
+      this.valuePanel = new System.Windows.Forms.Panel();
+      this.groupBox1 = new System.Windows.Forms.GroupBox();
+      this.groupBox2 = new System.Windows.Forms.GroupBox();
+      this.groupBox1.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // okButton
+      // 
+      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.okButton.Location = new System.Drawing.Point(135, 198);
+      this.okButton.Name = "okButton";
+      this.okButton.Size = new System.Drawing.Size(75, 23);
+      this.okButton.TabIndex = 0;
+      this.okButton.Text = "&OK";
+      this.okButton.UseVisualStyleBackColor = true;
+      this.okButton.Click += new System.EventHandler(this.okButton_Click);
+      // 
+      // cancelButton
+      // 
+      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+      this.cancelButton.Location = new System.Drawing.Point(216, 198);
+      this.cancelButton.Name = "cancelButton";
+      this.cancelButton.Size = new System.Drawing.Size(75, 23);
+      this.cancelButton.TabIndex = 1;
+      this.cancelButton.Text = "&Cancel";
+      this.cancelButton.UseVisualStyleBackColor = true;
+      // 
+      // keyPanel
+      // 
+      this.keyPanel.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.keyPanel.AutoScroll = true;
+      this.keyPanel.Location = new System.Drawing.Point(15, 31);
+      this.keyPanel.Name = "keyPanel";
+      this.keyPanel.Size = new System.Drawing.Size(276, 39);
+      this.keyPanel.TabIndex = 2;
+      // 
+      // valuePanel
+      // 
+      this.valuePanel.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.valuePanel.AutoScroll = true;
+      this.valuePanel.Location = new System.Drawing.Point(9, 19);
+      this.valuePanel.Name = "valuePanel";
+      this.valuePanel.Size = new System.Drawing.Size(270, 80);
+      this.valuePanel.TabIndex = 3;
+      // 
+      // groupBox1
+      // 
+      this.groupBox1.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.groupBox1.Controls.Add(this.valuePanel);
+      this.groupBox1.Location = new System.Drawing.Point(12, 82);
+      this.groupBox1.Name = "groupBox1";
+      this.groupBox1.Size = new System.Drawing.Size(283, 109);
+      this.groupBox1.TabIndex = 4;
+      this.groupBox1.TabStop = false;
+      this.groupBox1.Text = "Value: ";
+      // 
+      // groupBox2
+      // 
+      this.groupBox2.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.groupBox2.Location = new System.Drawing.Point(12, 12);
+      this.groupBox2.Name = "groupBox2";
+      this.groupBox2.Size = new System.Drawing.Size(283, 64);
+      this.groupBox2.TabIndex = 5;
+      this.groupBox2.TabStop = false;
+      this.groupBox2.Text = "Key:";
+      // 
+      // EditKeyValueDialog
+      // 
+      this.AcceptButton = this.okButton;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.CancelButton = this.cancelButton;
+      this.ClientSize = new System.Drawing.Size(301, 233);
+      this.Controls.Add(this.groupBox1);
+      this.Controls.Add(this.keyPanel);
+      this.Controls.Add(this.cancelButton);
+      this.Controls.Add(this.okButton);
+      this.Controls.Add(this.groupBox2);
+      this.Name = "EditKeyValueDialog";
+      this.Text = "KeyValuePair";
+      this.groupBox1.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button okButton;
+    private System.Windows.Forms.Button cancelButton;
+    private System.Windows.Forms.Panel keyPanel;
+    private System.Windows.Forms.Panel valuePanel;
+    private System.Windows.Forms.GroupBox groupBox1;
+    private System.Windows.Forms.GroupBox groupBox2;
+  }
+}
Index: trunk/sources/HeuristicLab.Data/EditKeyValueDialog.resx
===================================================================
--- trunk/sources/HeuristicLab.Data/EditKeyValueDialog.resx	(revision 187)
+++ trunk/sources/HeuristicLab.Data/EditKeyValueDialog.resx	(revision 187)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: trunk/sources/HeuristicLab.Data/HeuristicLab.Data.csproj
===================================================================
--- trunk/sources/HeuristicLab.Data/HeuristicLab.Data.csproj	(revision 186)
+++ trunk/sources/HeuristicLab.Data/HeuristicLab.Data.csproj	(revision 187)
@@ -112,4 +112,17 @@
       <DependentUpon>ConstrainedDoubleDataView.cs</DependentUpon>
     </Compile>
+    <Compile Include="EditKeyValueDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="EditKeyValueDialog.designer.cs">
+      <DependentUpon>EditKeyValueDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ItemDictionaryView_T.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ItemDictionaryView_T.designer.cs">
+      <DependentUpon>ItemDictionaryView_T.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ItemDictionary_T.cs" />
     <Compile Include="NullData.cs" />
     <Compile Include="IntMatrixDataView.cs">
@@ -226,7 +239,13 @@
       <SubType>Designer</SubType>
     </EmbeddedResource>
+    <EmbeddedResource Include="EditKeyValueDialog.resx">
+      <DependentUpon>EditKeyValueDialog.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="IntDataView.resx">
       <DependentUpon>IntDataView.cs</DependentUpon>
       <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="ItemDictionaryView_T.resx">
+      <DependentUpon>ItemDictionaryView_T.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="ItemListView_T.resx">
Index: trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.cs	(revision 187)
+++ trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.cs	(revision 187)
@@ -0,0 +1,176 @@
+﻿using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Data {
+  public partial class ItemDictionaryView<K, V> : ViewBase 
+    where K : IItem
+    where V : IItem {
+
+    private EditKeyValueDialog editKeyValueDialog;
+
+    public ItemDictionary<K,V> ItemDictionary {
+      get { return (ItemDictionary<K,V>) Item; }
+      set { base.Item = value; }
+    }
+
+    private ListViewItem CreateListViewItem(K key, V value) {
+      ListViewItem item = new ListViewItem(key.ToString());
+      item.Name = key.ToString();
+      item.SubItems.Add(value.ToString());
+      item.SubItems[0].Tag = key;
+      item.SubItems[1].Tag = value;
+      return item;
+    }
+
+    public ItemDictionaryView() : this(new ItemDictionary<K,V>()) { }
+
+    public ItemDictionaryView(ItemDictionary<K,V> dictionary) {
+      InitializeComponent();
+      ItemDictionary = dictionary;
+      ImageList imageListSmall = new ImageList();
+      listView.SmallImageList = imageListSmall;
+      listView.View = View.Details;
+      imageListSmall.Images.Add(Bitmap.FromFile(@"C:\Documents and Settings\Monika Kofler\Desktop\material.bmp"));
+      imageListSmall.Images.Add(Bitmap.FromFile(@"C:\Documents and Settings\Monika Kofler\Desktop\demand.bmp"));
+      imageListSmall.Images.Add(Bitmap.FromFile(@"C:\Documents and Settings\Monika Kofler\Desktop\job.bmp"));
+      imageListSmall.Images.Add(Bitmap.FromFile(@"C:\Documents and Settings\Monika Kofler\Desktop\tool.bmp"));
+      listView.Columns[0].Text = "Key";
+      listView.Columns[1].Text = "Value";
+      valueTypeTextBox.Text = typeof(V).ToString();
+      keyTypeTextBox.Text = typeof(K).ToString(); 
+    }
+
+    protected override void RemoveItemEvents() {
+      ItemDictionary.ItemAdded -= new EventHandler<KeyValueEventArgs>(ItemDictionary_ItemInserted);
+      ItemDictionary.ItemRemoved -= new EventHandler<KeyValueEventArgs>(ItemDictionary_ItemRemoved);
+      ItemDictionary.Cleared -= new EventHandler(ItemDictionary_Cleared);
+      base.RemoveItemEvents();
+    }
+
+    protected override void AddItemEvents() {
+      base.AddItemEvents();
+      ItemDictionary.ItemAdded += new EventHandler<KeyValueEventArgs>(ItemDictionary_ItemInserted);
+      ItemDictionary.ItemRemoved += new EventHandler<KeyValueEventArgs>(ItemDictionary_ItemRemoved);
+      ItemDictionary.Cleared += new EventHandler(ItemDictionary_Cleared);
+    }
+
+    private void listView_SelectedIndexChanged(object sender, EventArgs e) {
+      if (detailsPanel.Controls.Count > 0)
+        detailsPanel.Controls[0].Dispose();
+      if (keyPanel.Controls.Count > 0)
+        keyPanel.Controls[0].Dispose();
+      detailsPanel.Controls.Clear();
+      keyPanel.Controls.Clear();
+      detailsPanel.Enabled = false;
+      keyPanel.Enabled = false;
+      removeButton.Enabled = false;
+      if (listView.SelectedItems.Count > 0) {
+        removeButton.Enabled = true;
+      }
+      if (listView.SelectedItems.Count == 1) {
+        K key = (K) listView.SelectedItems[0].SubItems[0].Tag;
+        V data = (V) listView.SelectedItems[0].SubItems[1].Tag;
+        Control keyView = (Control) key.CreateView();
+        Control dataView = (Control) data.CreateView();
+        keyPanel.Controls.Add(keyView);
+        detailsPanel.Controls.Add(dataView);
+        detailsPanel.Enabled = true;
+      }
+      keyPanel.Enabled = false;
+    }
+
+    #region Item and ItemDictionary Events
+    private void ItemDictionary_ItemInserted(object sender, KeyValueEventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler<KeyValueEventArgs>(ItemDictionary_ItemInserted), sender, e);
+      else {
+        ListViewItem item = CreateListViewItem((K) e.Key, (V) e.Value);
+        listView.Items.Insert(listView.Items.Count, item);
+        item.Name = e.Key.ToString();
+        e.Value.Changed += new EventHandler(Item_Changed);
+        e.Key.Changed += new EventHandler(Item_Changed);
+      }
+    }
+
+    private void ItemDictionary_ItemRemoved(object sender, KeyValueEventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler<KeyValueEventArgs>(ItemDictionary_ItemRemoved), sender, e);
+      else {
+        int index = listView.Items.IndexOfKey(e.Key.ToString());
+        listView.Items.RemoveAt(index);
+        e.Key.Changed -= new EventHandler(Item_Changed);
+        e.Value.Changed += new EventHandler(Item_Changed);
+      }
+    }
+
+    private void ItemDictionary_Cleared(object sender, EventArgs e) {
+      Refresh();
+    }
+
+    private void Item_Changed(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Item_Changed), sender, e);
+      else {
+        IItem data = (IItem) sender;
+        foreach (ListViewItem item in listView.Items) {
+          if (item.SubItems[0].Tag == data) {
+            item.SubItems[0].Text = data.ToString();
+            item.Name = data.ToString();
+          } else if (item.SubItems[1].Tag == data) {
+            item.SubItems[1].Text = data.ToString();
+          }
+        }
+      }
+    }
+    #endregion
+
+    #region Update Controls
+    protected override void UpdateControls() {
+      base.UpdateControls();
+      detailsPanel.Controls.Clear();
+      keyPanel.Controls.Clear();
+      detailsPanel.Enabled = false;
+      keyPanel.Enabled = false;
+      removeButton.Enabled = false;
+
+      foreach (ListViewItem item in listView.Items) {
+        ((IItem) item.SubItems[0]).Changed -= new EventHandler(Item_Changed);
+        ((IItem) item.SubItems[1]).Changed -= new EventHandler(Item_Changed);
+      }
+      listView.Items.Clear();
+      foreach (KeyValuePair<K, V> data in ItemDictionary) {
+        ListViewItem item = CreateListViewItem(data.Key, data.Value);
+        listView.Items.Add(item);
+        data.Key.Changed += new EventHandler(Item_Changed);
+        data.Value.Changed += new EventHandler(Item_Changed);
+      }
+    }
+    #endregion
+
+    #region Button Events
+    private void addButton_Click(object sender, EventArgs e) {
+      editKeyValueDialog = new EditKeyValueDialog(typeof(K), typeof(V));
+      if (editKeyValueDialog.ShowDialog(this) == DialogResult.OK) {
+        try {
+          if (!ItemDictionary.ContainsKey((K) editKeyValueDialog.Key)) {
+            ItemDictionary.Add((K) editKeyValueDialog.Key, (V) editKeyValueDialog.Value);
+          }
+        } catch (Exception ex) {
+          Auxiliary.ShowErrorMessageBox(ex);
+        }
+      }
+    }
+
+    private void removeButton_Click(object sender, EventArgs e) {
+      while (listView.SelectedIndices.Count > 0)
+        ItemDictionary.Remove((K) listView.SelectedItems[0].SubItems[0].Tag);
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.designer.cs	(revision 187)
+++ trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.designer.cs	(revision 187)
@@ -0,0 +1,210 @@
+﻿namespace HeuristicLab.Data {
+  partial class ItemDictionaryView<K, V> {
+    /// <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 && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component 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.groupBox1 = new System.Windows.Forms.GroupBox();
+      this.removeButton = new System.Windows.Forms.Button();
+      this.addButton = new System.Windows.Forms.Button();
+      this.listView = new System.Windows.Forms.ListView();
+      this.keyHeader = new System.Windows.Forms.ColumnHeader();
+      this.valueHeader = new System.Windows.Forms.ColumnHeader();
+      this.label1 = new System.Windows.Forms.Label();
+      this.label2 = new System.Windows.Forms.Label();
+      this.keyTypeTextBox = new System.Windows.Forms.TextBox();
+      this.valueTypeTextBox = new System.Windows.Forms.TextBox();
+      this.detailsPanel = new System.Windows.Forms.Panel();
+      this.keyPanel = new System.Windows.Forms.Panel();
+      this.groupBox2 = new System.Windows.Forms.GroupBox();
+      this.groupBox3 = new System.Windows.Forms.GroupBox();
+      this.groupBox1.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // groupBox1
+      // 
+      this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)));
+      this.groupBox1.Controls.Add(this.removeButton);
+      this.groupBox1.Controls.Add(this.addButton);
+      this.groupBox1.Controls.Add(this.listView);
+      this.groupBox1.Location = new System.Drawing.Point(5, 70);
+      this.groupBox1.Name = "groupBox1";
+      this.groupBox1.Size = new System.Drawing.Size(170, 175);
+      this.groupBox1.TabIndex = 0;
+      this.groupBox1.TabStop = false;
+      this.groupBox1.Text = "KeyValuePairs:";
+      // 
+      // removeButton
+      // 
+      this.removeButton.Location = new System.Drawing.Point(89, 145);
+      this.removeButton.Name = "removeButton";
+      this.removeButton.Size = new System.Drawing.Size(75, 23);
+      this.removeButton.TabIndex = 2;
+      this.removeButton.Text = "&Remove";
+      this.removeButton.UseVisualStyleBackColor = true;
+      this.removeButton.Click += new System.EventHandler(this.removeButton_Click);
+      // 
+      // addButton
+      // 
+      this.addButton.Location = new System.Drawing.Point(8, 145);
+      this.addButton.Name = "addButton";
+      this.addButton.Size = new System.Drawing.Size(75, 23);
+      this.addButton.TabIndex = 1;
+      this.addButton.Text = "&Add...";
+      this.addButton.UseVisualStyleBackColor = true;
+      this.addButton.Click += new System.EventHandler(this.addButton_Click);
+      // 
+      // listView
+      // 
+      this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.keyHeader,
+            this.valueHeader});
+      this.listView.Location = new System.Drawing.Point(7, 19);
+      this.listView.Name = "listView";
+      this.listView.Size = new System.Drawing.Size(157, 120);
+      this.listView.TabIndex = 0;
+      this.listView.UseCompatibleStateImageBehavior = false;
+      this.listView.SelectedIndexChanged += new System.EventHandler(this.listView_SelectedIndexChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(11, 12);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(52, 13);
+      this.label1.TabIndex = 1;
+      this.label1.Text = "KeyType:";
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(11, 40);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(61, 13);
+      this.label2.TabIndex = 2;
+      this.label2.Text = "ValueType:";
+      // 
+      // keyTypeTextBox
+      // 
+      this.keyTypeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.keyTypeTextBox.BackColor = System.Drawing.SystemColors.ControlLight;
+      this.keyTypeTextBox.Location = new System.Drawing.Point(73, 5);
+      this.keyTypeTextBox.Name = "keyTypeTextBox";
+      this.keyTypeTextBox.Size = new System.Drawing.Size(301, 20);
+      this.keyTypeTextBox.TabIndex = 3;
+      // 
+      // valueTypeTextBox
+      // 
+      this.valueTypeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.valueTypeTextBox.BackColor = System.Drawing.SystemColors.ControlLight;
+      this.valueTypeTextBox.Location = new System.Drawing.Point(73, 33);
+      this.valueTypeTextBox.Name = "valueTypeTextBox";
+      this.valueTypeTextBox.Size = new System.Drawing.Size(301, 20);
+      this.valueTypeTextBox.TabIndex = 4;
+      // 
+      // detailsPanel
+      // 
+      this.detailsPanel.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.detailsPanel.AutoScroll = true;
+      this.detailsPanel.ForeColor = System.Drawing.SystemColors.ControlText;
+      this.detailsPanel.Location = new System.Drawing.Point(187, 164);
+      this.detailsPanel.Name = "detailsPanel";
+      this.detailsPanel.Size = new System.Drawing.Size(187, 76);
+      this.detailsPanel.TabIndex = 9;
+      // 
+      // keyPanel
+      // 
+      this.keyPanel.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.keyPanel.AutoScroll = true;
+      this.keyPanel.ForeColor = System.Drawing.SystemColors.ControlText;
+      this.keyPanel.Location = new System.Drawing.Point(187, 90);
+      this.keyPanel.Name = "keyPanel";
+      this.keyPanel.Size = new System.Drawing.Size(187, 43);
+      this.keyPanel.TabIndex = 0;
+      // 
+      // groupBox2
+      // 
+      this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.groupBox2.Location = new System.Drawing.Point(180, 70);
+      this.groupBox2.Name = "groupBox2";
+      this.groupBox2.Size = new System.Drawing.Size(198, 69);
+      this.groupBox2.TabIndex = 10;
+      this.groupBox2.TabStop = false;
+      this.groupBox2.Text = "Key:";
+      // 
+      // groupBox3
+      // 
+      this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.groupBox3.Location = new System.Drawing.Point(181, 145);
+      this.groupBox3.Name = "groupBox3";
+      this.groupBox3.Size = new System.Drawing.Size(197, 100);
+      this.groupBox3.TabIndex = 11;
+      this.groupBox3.TabStop = false;
+      this.groupBox3.Text = "Value:";
+      // 
+      // ItemDictionaryView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.keyPanel);
+      this.Controls.Add(this.detailsPanel);
+      this.Controls.Add(this.valueTypeTextBox);
+      this.Controls.Add(this.keyTypeTextBox);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.groupBox1);
+      this.Controls.Add(this.groupBox2);
+      this.Controls.Add(this.groupBox3);
+      this.Name = "ItemDictionaryView";
+      this.Size = new System.Drawing.Size(381, 253);
+      this.groupBox1.ResumeLayout(false);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.GroupBox groupBox1;
+    private System.Windows.Forms.Button removeButton;
+    private System.Windows.Forms.Button addButton;
+    private System.Windows.Forms.ListView listView;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.TextBox keyTypeTextBox;
+    private System.Windows.Forms.TextBox valueTypeTextBox;
+    private System.Windows.Forms.ColumnHeader keyHeader;
+    private System.Windows.Forms.ColumnHeader valueHeader;
+    private System.Windows.Forms.Panel detailsPanel;
+    private System.Windows.Forms.Panel keyPanel;
+    private System.Windows.Forms.GroupBox groupBox2;
+    private System.Windows.Forms.GroupBox groupBox3;
+  }
+}
Index: trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.resx
===================================================================
--- trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.resx	(revision 187)
+++ trunk/sources/HeuristicLab.Data/ItemDictionaryView_T.resx	(revision 187)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: trunk/sources/HeuristicLab.Data/ItemDictionary_T.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/ItemDictionary_T.cs	(revision 187)
+++ trunk/sources/HeuristicLab.Data/ItemDictionary_T.cs	(revision 187)
@@ -0,0 +1,205 @@
+﻿using System;
+using System.Collections; 
+using System.Collections.Generic;
+using System.Text;
+using System.Xml;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Data {
+  public class ItemDictionary<K,V> : ItemBase, IDictionary<K,V> 
+    where K : IItem
+    where V : IItem{
+    private Dictionary<K, V> dict;
+
+    public Dictionary<K, V> Dictionary {
+      get { return dict; }
+    }
+
+    public ItemDictionary() {
+      dict = new Dictionary<K, V>(new IItemKeyComparer<K>());
+    }
+
+    #region ItemBase Members
+    public override IView CreateView() {
+      return new ItemDictionaryView<K,V>(this);
+    }
+
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      ItemDictionary<K,V> clone = new ItemDictionary<K,V>();
+      clonedObjects.Add(Guid, clone);
+      foreach (KeyValuePair<K, V> item in dict) {
+        clone.dict.Add((K) Auxiliary.Clone(item.Key, clonedObjects), (V) Auxiliary.Clone(item.Value, clonedObjects));
+      }
+      return clone;
+    }
+
+    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
+      foreach (KeyValuePair<K, V> item in dict) {
+        XmlNode keyNode = PersistenceManager.Persist("Key", item.Key, document, persistedObjects);
+        XmlNode valueNode = PersistenceManager.Persist("Val", item.Value, document, persistedObjects); 
+        XmlNode pairNode = document.CreateNode(XmlNodeType.Element, "KeyValuePair", null); 
+        pairNode.AppendChild(keyNode); 
+        pairNode.AppendChild(valueNode); 
+        node.AppendChild(pairNode); 
+      }
+      return node; 
+    }
+
+    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      for (int i = 0; i < node.ChildNodes.Count; i++) {
+        K key = (K) PersistenceManager.Restore(node.ChildNodes[i].SelectSingleNode("Key"), restoredObjects);
+        V val = (V) PersistenceManager.Restore(node.ChildNodes[i].SelectSingleNode("Val"), restoredObjects);
+        dict[key] = val; 
+      }
+    }
+
+    public override string ToString() {
+      if (dict.Count > 0) {
+        StringBuilder builder = new StringBuilder();
+        foreach (KeyValuePair<K, V> item in dict) {
+          builder.Append(item.Key.ToString());
+          builder.Append(":");
+          builder.Append(item.Value.ToString());
+          builder.Append("; ");
+        }
+        return builder.ToString();
+      } else {
+        return "Empty Dictionary";
+      }
+    }
+    #endregion
+
+    #region IDictionary<K,V> Members
+
+    public void Add(K key, V value) {
+      dict.Add(key, value);
+      OnItemAdded(key, value);
+    }
+
+    public bool ContainsKey(K key) {
+      return dict.ContainsKey(key);
+    }
+
+    public ICollection<K> Keys {
+      get { return dict.Keys; }
+    }
+
+    public bool Remove(K key) {
+      V value = dict[key]; 
+      bool removed = dict.Remove(key);
+      OnItemRemoved(key, value); 
+      return removed; 
+    }
+
+    public bool TryGetValue(K key, out V value) {
+      return dict.TryGetValue(key, out value);
+    }
+
+    public ICollection<V> Values {
+      get { return dict.Values; }
+    }
+
+    public V this[K key] {
+      get { return dict[key]; }
+      set { dict[key] = value; }
+    }
+
+    #endregion
+
+    #region ICollection<KeyValuePair<K,V>> Members
+
+    public void Add(KeyValuePair<K, V> item) {
+      dict.Add(item.Key, item.Value);
+      OnItemAdded(item.Key, item.Value); 
+    }
+
+    public void Clear() {
+      dict.Clear();
+      OnCleared(); 
+    }
+
+    public bool Contains(KeyValuePair<K, V> item) {
+      return (dict.ContainsKey(item.Key) && dict[item.Key].Equals(item.Value));
+    }
+
+    public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) {
+      throw new NotImplementedException(); 
+    }
+
+    public int Count {
+      get { return dict.Count; }
+    }
+
+    public bool IsReadOnly {
+      get { return false; }
+    }
+
+    public bool Remove(KeyValuePair<K, V> item) {
+      bool removed = dict.Remove(item.Key);
+      if (removed) {
+        OnItemRemoved(item.Key, item.Value);
+      } 
+      return removed; 
+    }
+    #endregion
+
+    #region IEnumerable<KeyValuePair<K,V>> Members
+    public IEnumerator<KeyValuePair<K, V>> GetEnumerator() {
+      return dict.GetEnumerator();
+    }
+    #endregion
+
+    #region IEnumerable Members
+    IEnumerator IEnumerable.GetEnumerator() {
+      return dict.GetEnumerator();
+    }
+    #endregion
+
+    #region Event Handler
+    public event EventHandler<KeyValueEventArgs> ItemAdded;
+    protected virtual void OnItemAdded(K key, V value) {
+      if (ItemAdded != null)
+        ItemAdded(this, new KeyValueEventArgs(key, value));
+      OnChanged();
+    }
+
+    public event EventHandler<KeyValueEventArgs> ItemRemoved;
+    protected virtual void OnItemRemoved(K key, V value) {
+      if (ItemRemoved != null)
+        ItemRemoved(this, new KeyValueEventArgs(key, value));
+      OnChanged();
+    }
+
+    public event EventHandler Cleared;
+    protected virtual void OnCleared() {
+      if (Cleared != null)
+        Cleared(this, new EventArgs());
+      OnChanged();
+    }
+    #endregion
+
+    #region IEqualityComparer
+    internal sealed class IItemKeyComparer<T> : IEqualityComparer<T>
+        where T : IItem {
+      public bool Equals(T x, T y) {
+        if (x is IComparable) {
+          return (((IComparable) x).CompareTo(y) == 0); 
+        }
+        if (y is IComparable) {
+          return (((IComparable) y).CompareTo(x) == 0); 
+        }
+        return x.Equals(y); 
+      }
+
+      public int GetHashCode(T obj) {
+        if (obj is IObjectData) {
+          return ((IObjectData) obj).Data.GetHashCode(); 
+        }
+        return obj.Guid.GetHashCode(); 
+      }
+    }
+    #endregion
+  }
+}
