Index: /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.2/AsynchronousContentView.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.2/AsynchronousContentView.cs	(revision 3328)
+++ /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.2/AsynchronousContentView.cs	(revision 3329)
@@ -25,9 +25,11 @@
     /// <param name="method">The delegate to invoke.</param>
     protected new void Invoke(Delegate method) {
-      // prevent blocking of worker thread in Invoke, if the control is disposed
+      // prevents blocking of worker thread in Invoke, if the control is disposed
+      if (!IsHandleCreated)
+        return;
       IAsyncResult result = BeginInvoke(method);
       result.AsyncWaitHandle.WaitOne(1000, false);
-      if (result.IsCompleted) try { EndInvoke(result); } catch (ObjectDisposedException) { }
-      else {
+      if (result.IsCompleted) try { EndInvoke(result); }
+        catch (ObjectDisposedException) { } else {
         ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
           new WaitOrTimerCallback((x, b) => { try { EndInvoke(result); } catch (ObjectDisposedException) { } }),
@@ -42,5 +44,7 @@
     /// <param name="args">The invoke arguments.</param>
     protected new void Invoke(Delegate method, params object[] args) {
-      // prevent blocking of worker thread in Invoke, if the control is disposed
+      // prevents blocking of worker thread in Invoke, if the control is disposed
+      if (!IsHandleCreated)
+        return;
       IAsyncResult result = BeginInvoke(method, args);
       result.AsyncWaitHandle.WaitOne(1000, false);
Index: /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.Designer.cs	(revision 3328)
+++ /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.Designer.cs	(revision 3329)
@@ -45,7 +45,9 @@
     /// </summary>
     private void InitializeComponent() {
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExperimentView));
       this.tabControl = new System.Windows.Forms.TabControl();
       this.optimizersTabPage = new System.Windows.Forms.TabPage();
       this.optimizerListView = new HeuristicLab.Optimization.Views.OptimizerListView();
+      this.runsTabPage = new System.Windows.Forms.TabPage();
       this.startButton = new System.Windows.Forms.Button();
       this.stopButton = new System.Windows.Forms.Button();
@@ -54,6 +56,5 @@
       this.executionTimeTextBox = new System.Windows.Forms.TextBox();
       this.pauseButton = new System.Windows.Forms.Button();
-      this.runsTabPage = new System.Windows.Forms.TabPage();
-      this.runsView = new HeuristicLab.Optimization.Views.RunCollectionView();
+      this.runsViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
@@ -108,8 +109,19 @@
       this.optimizerListView.TabIndex = 0;
       // 
+      // runsTabPage
+      // 
+      this.runsTabPage.Controls.Add(this.runsViewHost);
+      this.runsTabPage.Location = new System.Drawing.Point(4, 22);
+      this.runsTabPage.Name = "runsTabPage";
+      this.runsTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.runsTabPage.Size = new System.Drawing.Size(671, 374);
+      this.runsTabPage.TabIndex = 2;
+      this.runsTabPage.Text = "Runs";
+      this.runsTabPage.UseVisualStyleBackColor = true;
+      // 
       // startButton
       // 
       this.startButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-      this.startButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Play;
+      this.startButton.Image = ((System.Drawing.Image)(resources.GetObject("startButton.Image")));
       this.startButton.Location = new System.Drawing.Point(0, 458);
       this.startButton.Name = "startButton";
@@ -123,5 +135,5 @@
       // 
       this.stopButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-      this.stopButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Stop;
+      this.stopButton.Image = ((System.Drawing.Image)(resources.GetObject("stopButton.Image")));
       this.stopButton.Location = new System.Drawing.Point(60, 458);
       this.stopButton.Name = "stopButton";
@@ -135,5 +147,5 @@
       // 
       this.resetButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-      this.resetButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Restart;
+      this.resetButton.Image = ((System.Drawing.Image)(resources.GetObject("resetButton.Image")));
       this.resetButton.Location = new System.Drawing.Point(90, 458);
       this.resetButton.Name = "resetButton";
@@ -166,5 +178,5 @@
       // 
       this.pauseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-      this.pauseButton.Image = HeuristicLab.Common.Resources.VS2008ImageLibrary.Pause;
+      this.pauseButton.Image = ((System.Drawing.Image)(resources.GetObject("pauseButton.Image")));
       this.pauseButton.Location = new System.Drawing.Point(30, 458);
       this.pauseButton.Name = "pauseButton";
@@ -175,26 +187,15 @@
       this.pauseButton.Click += new System.EventHandler(this.pauseButton_Click);
       // 
-      // runsTabPage
-      // 
-      this.runsTabPage.Controls.Add(this.runsView);
-      this.runsTabPage.Location = new System.Drawing.Point(4, 22);
-      this.runsTabPage.Name = "runsTabPage";
-      this.runsTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.runsTabPage.Size = new System.Drawing.Size(671, 374);
-      this.runsTabPage.TabIndex = 2;
-      this.runsTabPage.Text = "Runs";
-      this.runsTabPage.UseVisualStyleBackColor = true;
-      // 
-      // runsView
-      // 
-      this.runsView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+      // runsViewHost
+      // 
+      this.runsViewHost.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.runsView.Caption = "RunCollection";
-      this.runsView.Content = null;
-      this.runsView.Location = new System.Drawing.Point(6, 6);
-      this.runsView.Name = "runsView";
-      this.runsView.Size = new System.Drawing.Size(659, 362);
-      this.runsView.TabIndex = 0;
+      this.runsViewHost.Content = null;
+      this.runsViewHost.Location = new System.Drawing.Point(2, 6);
+      this.runsViewHost.Name = "runsViewHost";
+      this.runsViewHost.Size = new System.Drawing.Size(663, 362);
+      this.runsViewHost.TabIndex = 0;
+      this.runsViewHost.ViewType = null;
       // 
       // ExperimentView
@@ -242,5 +243,5 @@
     private OptimizerListView optimizerListView;
     private System.Windows.Forms.TabPage runsTabPage;
-    private RunCollectionView runsView;
+    private HeuristicLab.MainForm.WindowsForms.ViewHost runsViewHost;
 
   }
Index: /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.cs	(revision 3328)
+++ /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.cs	(revision 3329)
@@ -71,5 +71,5 @@
       if (Content == null) {
         optimizerListView.Content = null;
-        runsView.Content = null;
+        runsViewHost.Content = null;
         tabControl.Enabled = false;
         startButton.Enabled = pauseButton.Enabled = stopButton.Enabled = resetButton.Enabled = false;
@@ -78,5 +78,5 @@
       } else {
         optimizerListView.Content = Content.Optimizers;
-        runsView.Content = Content.Runs;
+        runsViewHost.Content = Content.Runs;
         tabControl.Enabled = true;
         EnableDisableButtons();
Index: /trunk/sources/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 3328)
+++ /trunk/sources/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 3329)
@@ -180,4 +180,8 @@
       <Name>HeuristicLab.Core-3.3</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.MainForm.WindowsForms\3.2\HeuristicLab.MainForm.WindowsForms-3.2.csproj">
       <Project>{AB687BBE-1BFE-476B-906D-44237135431D}</Project>
Index: /trunk/sources/HeuristicLab.Optimization/3.3/RunCollection.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization/3.3/RunCollection.cs	(revision 3328)
+++ /trunk/sources/HeuristicLab.Optimization/3.3/RunCollection.cs	(revision 3329)
@@ -20,16 +20,184 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Common;
 
 namespace HeuristicLab.Optimization {
   [StorableClass]
   [Item("RunCollection", "Represents a collection of runs.")]
-  public class RunCollection : ItemCollection<IRun> {
-    public RunCollection() : base() { }
-    public RunCollection(int capacity) : base(capacity) { }
-    public RunCollection(IEnumerable<IRun> collection) : base(collection) { }
+  public class RunCollection : ItemCollection<IRun>, IStringConvertibleMatrix {
+    public RunCollection() : base() { Initialize(); }
+    public RunCollection(int capacity) : base(capacity) { Initialize(); }
+    public RunCollection(IEnumerable<IRun> collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); }
+
+    protected static Type[] viewableDataTypes = new Type[]{typeof(BoolValue), typeof(DoubleValue), typeof(IntValue),
+      typeof(PercentValue), typeof(StringValue)};
+
+    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
+      parameterNames.Clear();
+      resultNames.Clear();
+      foreach (IRun run in items) {
+        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
+          AddParameter(parameter.Key, parameter.Value);
+        foreach (KeyValuePair<string, IItem> result in run.Results)
+          AddResult(result.Key, result.Value);
+      }
+      base.OnCollectionReset(items, oldItems);
+      OnReset();
+      OnColumnNamesChanged();
+      OnRowNamesChanged();
+    }
+    protected override void OnItemsAdded(IEnumerable<IRun> items) {
+      bool columnNamesChanged = false;
+      foreach (IRun run in items) {
+        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
+          columnNamesChanged |= AddParameter(parameter.Key, parameter.Value);
+        foreach (KeyValuePair<string, IItem> result in run.Results)
+          columnNamesChanged |= AddResult(result.Key, result.Value);
+      }
+      base.OnItemsAdded(items);
+      OnReset();
+      if (columnNamesChanged)
+        OnColumnNamesChanged();
+      OnRowNamesChanged();
+    }
+    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
+      bool columnNamesChanged = false;
+      foreach (IRun run in items) {
+        foreach (string parameterName in run.Parameters.Keys)
+          columnNamesChanged |= RemoveParameterName(parameterName);
+        foreach (string resultName in run.Results.Keys)
+          columnNamesChanged |= RemoveResultName(resultName);
+      }
+      base.OnItemsRemoved(items);
+      OnReset();
+      if (columnNamesChanged)
+        OnColumnNamesChanged();
+      OnRowNamesChanged();
+    }
+
+    private void Initialize() {
+      parameterNames = new List<string>();
+      resultNames = new List<string>();
+      this.ReadOnlyView = true;
+    }
+
+    private bool AddParameter(string name, IItem value) {
+      if (value == null)
+        return false;
+      if (!parameterNames.Contains(name) &&
+          viewableDataTypes.Any(x => x.IsAssignableFrom(value.GetType()))) {
+        parameterNames.Add(name);
+        return true;
+      }
+      return false;
+    }
+    private bool AddResult(string name, IItem value) {
+      if (value == null)
+        return false;
+      if (!resultNames.Contains(name) &&
+          viewableDataTypes.Any(x => x.IsAssignableFrom(value.GetType()))) {
+        resultNames.Add(name);
+        return true;
+      }
+      return false;
+    }
+    private bool RemoveParameterName(string name) {
+      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
+        parameterNames.Remove(name);
+        return true;
+      }
+      return false;
+    }
+    private bool RemoveResultName(string name) {
+      if (!list.Any(x => x.Results.ContainsKey(name))) {
+        resultNames.Remove(name);
+        return true;
+      }
+      return false;
+    }
+
+    #region IStringConvertibleMatrix Members
+    private List<string> parameterNames;
+    private List<string> resultNames;
+    public int Rows {
+      get { return this.Count; }
+      set { throw new System.NotImplementedException(); }
+    }
+    public int Columns {
+      get { return parameterNames.Count + resultNames.Count; }
+      set { throw new NotSupportedException(); }
+    }
+    public IEnumerable<string> ColumnNames {
+      get {
+        List<string> value = new List<string>(parameterNames);
+        value.AddRange(resultNames);
+        return value;
+      }
+      set { throw new NotSupportedException(); }
+    }
+    public IEnumerable<string> RowNames {
+      get { return list.Select(x => x.Name).ToList(); }
+      set { throw new NotSupportedException(); }
+    }
+    public bool SortableView {
+      get { return true; }
+      set { throw new NotSupportedException(); }
+    }
+
+    public string GetValue(int rowIndex, int columnIndex) {
+      IRun run = this.list[rowIndex];
+      string value = string.Empty;
+
+      if (columnIndex < parameterNames.Count) {
+        string parameterName = parameterNames[columnIndex];
+        if (run.Parameters.ContainsKey(parameterName)) {
+          IItem param = run.Parameters[parameterName];
+          if (param != null) value = param.ToString();
+        }
+      } else if (columnIndex < parameterNames.Count + resultNames.Count) {
+        string resultName = resultNames[columnIndex - parameterNames.Count];
+        if (run.Results.ContainsKey(resultName)) {
+          IItem result = run.Results[resultName];
+          if (result != null) value = result.ToString();
+        }
+      }
+      return value;
+    }
+
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
+      if (ItemChanged != null)
+        ItemChanged(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      OnToStringChanged();
+    }
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      if (Reset != null)
+        Reset(this, EventArgs.Empty);
+      OnToStringChanged();
+    }
+    public event EventHandler ColumnNamesChanged;
+    protected virtual void OnColumnNamesChanged() {
+      EventHandler handler = ColumnNamesChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowNamesChanged;
+    protected virtual void OnRowNamesChanged() {
+      EventHandler handler = RowNamesChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler SortableViewChanged;
+    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
+    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
+    #endregion
   }
 }
