Index: trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleArrayView.cs
===================================================================
--- trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleArrayView.cs	(revision 9652)
+++ trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleArrayView.cs	(revision 9657)
@@ -23,4 +23,5 @@
 using System.ComponentModel;
 using System.Drawing;
+using System.Linq;
 using System.Text;
 using System.Windows.Forms;
@@ -53,4 +54,5 @@
 
     protected override void DeregisterContentEvents() {
+      Content.ElementNamesChanged -= new EventHandler(Content_ElementNamesChanged);
       Content.ItemChanged -= new EventHandler<EventArgs<int>>(Content_ItemChanged);
       Content.Reset -= new EventHandler(Content_Reset);
@@ -62,4 +64,5 @@
       Content.ItemChanged += new EventHandler<EventArgs<int>>(Content_ItemChanged);
       Content.Reset += new EventHandler(Content_Reset);
+      Content.ElementNamesChanged += new EventHandler(Content_ElementNamesChanged);
     }
 
@@ -96,5 +99,23 @@
         dataGridView.Columns[0].Width = dataGridView.Columns[0].GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);
       }
+      UpdateRowHeaders();
+      dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders);
       dataGridView.Enabled = true;
+    }
+
+    protected virtual void UpdateRowHeaders() {
+      for (int i = 0; i < dataGridView.RowCount; i++) {
+        if (i < Content.ElementNames.Count())
+          dataGridView.Rows[i].HeaderCell.Value = Content.ElementNames.ElementAt(i);
+        else
+          dataGridView.Rows[i].HeaderCell.Value = string.Empty;
+      }
+    }
+
+    private void Content_ElementNamesChanged(object sender, EventArgs e) {
+      if (InvokeRequired)
+        Invoke(new EventHandler(Content_ElementNamesChanged), sender, e);
+      else
+        UpdateRowHeaders();
     }
 
Index: trunk/sources/HeuristicLab.Data/3.3/Interfaces/IStringConvertibleArray.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/3.3/Interfaces/IStringConvertibleArray.cs	(revision 9652)
+++ trunk/sources/HeuristicLab.Data/3.3/Interfaces/IStringConvertibleArray.cs	(revision 9657)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using HeuristicLab.Common;
 
@@ -26,4 +27,5 @@
   public interface IStringConvertibleArray : IContent {
     int Length { get; set; }
+    IEnumerable<string> ElementNames { get; set; }
 
     bool ReadOnly { get; }
@@ -33,4 +35,5 @@
     bool SetValue(string value, int index);
 
+    event EventHandler ElementNamesChanged;
     event EventHandler<EventArgs<int>> ItemChanged;
     event EventHandler Reset;
Index: trunk/sources/HeuristicLab.Data/3.3/StringArray.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/3.3/StringArray.cs	(revision 9652)
+++ trunk/sources/HeuristicLab.Data/3.3/StringArray.cs	(revision 9657)
@@ -43,4 +43,20 @@
     protected string[] array;
 
+    [Storable]
+    protected List<string> elementNames;
+    public virtual IEnumerable<string> ElementNames {
+      get { return this.elementNames; }
+      set {
+        if (ReadOnly) throw new NotSupportedException("ElementNames cannot be set. ValueTypeArray is read-only.");
+        if (value == null || !value.Any())
+          elementNames = new List<string>();
+        else if (value.Count() != Length)
+          throw new ArgumentException("An element name must be specified for each element.");
+        else
+          elementNames = new List<string>(value);
+        OnElementNamesChanged();
+      }
+    }
+
     public virtual int Length {
       get { return array.Length; }
@@ -49,4 +65,9 @@
         if (value != Length) {
           Array.Resize<string>(ref array, value);
+          while (elementNames.Count > value)
+            elementNames.RemoveAt(elementNames.Count - 1);
+          while (elementNames.Count < value)
+            elementNames.Add("Element " + elementNames.Count);
+          OnElementNamesChanged();
           OnReset();
         }
@@ -72,4 +93,9 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (elementNames == null) { elementNames = new List<string>(); }
+    }
+
     [StorableConstructor]
     protected StringArray(bool deserializing) : base(deserializing) { }
@@ -78,8 +104,10 @@
       this.array = (string[])original.array.Clone();
       this.readOnly = original.readOnly;
+      this.elementNames = new List<string>(original.elementNames);
     }
     public StringArray() {
       array = new string[0];
       readOnly = false;
+      elementNames = new List<string>();
     }
     public StringArray(int length) {
@@ -88,4 +116,5 @@
         array[i] = string.Empty;
       readOnly = false;
+      elementNames = new List<string>();
     }
     public StringArray(string[] elements) {
@@ -95,4 +124,5 @@
         array[i] = elements[i] == null ? string.Empty : elements[i];
       readOnly = false;
+      elementNames = new List<string>();
     }
 
@@ -153,4 +183,11 @@
     }
 
+    public event EventHandler ElementNamesChanged;
+    protected virtual void OnElementNamesChanged() {
+      EventHandler handler = ElementNamesChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
     public event EventHandler<EventArgs<int>> ItemChanged;
     protected virtual void OnItemChanged(int index) {
Index: trunk/sources/HeuristicLab.Data/3.3/ValueTypeArray.cs
===================================================================
--- trunk/sources/HeuristicLab.Data/3.3/ValueTypeArray.cs	(revision 9652)
+++ trunk/sources/HeuristicLab.Data/3.3/ValueTypeArray.cs	(revision 9657)
@@ -43,4 +43,20 @@
     protected T[] array;
 
+    [Storable]
+    protected List<string> elementNames;
+    public virtual IEnumerable<string> ElementNames {
+      get { return this.elementNames; }
+      set {
+        if (ReadOnly) throw new NotSupportedException("ElementNames cannot be set. ValueTypeArray is read-only.");
+        if (value == null || !value.Any())
+          elementNames = new List<string>();
+        else if (value.Count() != Length)
+          throw new ArgumentException("An element name must be specified for each element.");
+        else
+          elementNames = new List<string>(value);
+        OnElementNamesChanged();
+      }
+    }
+
     public virtual int Length {
       get { return array.Length; }
@@ -51,4 +67,9 @@
         if (value != Length) {
           Array.Resize<T>(ref array, value);
+          while (elementNames.Count > value)
+            elementNames.RemoveAt(elementNames.Count - 1);
+          while (elementNames.Count < value)
+            elementNames.Add("Element " + elementNames.Count);
+          OnElementNamesChanged();
           OnReset();
         }
@@ -73,4 +94,9 @@
     }
 
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (elementNames == null) { elementNames = new List<string>(); }
+    }
+
     [StorableConstructor]
     protected ValueTypeArray(bool deserializing) : base(deserializing) { }
@@ -79,12 +105,15 @@
       this.array = (T[])original.array.Clone();
       this.readOnly = original.readOnly;
+      this.elementNames = new List<string>(original.elementNames);
     }
     protected ValueTypeArray() {
       array = new T[0];
       readOnly = false;
+      elementNames = new List<string>();
     }
     protected ValueTypeArray(int length) {
       array = new T[length];
       readOnly = false;
+      elementNames = new List<string>();
     }
     protected ValueTypeArray(T[] elements) {
@@ -92,4 +121,5 @@
       array = (T[])elements.Clone();
       readOnly = false;
+      elementNames = new List<string>();
     }
 
@@ -125,4 +155,11 @@
     }
 
+    public event EventHandler ElementNamesChanged;
+    protected virtual void OnElementNamesChanged() {
+      EventHandler handler = ElementNamesChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
     public event EventHandler<EventArgs<int>> ItemChanged;
     protected virtual void OnItemChanged(int index) {
