Index: /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs
===================================================================
--- /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs	(revision 12553)
+++ /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs	(revision 12554)
@@ -35,4 +35,6 @@
   [Content(typeof(RecursiveDataItem), false)]
   public partial class BubbleChartView : ItemView {
+    private const string Separator = ":";
+
     private enum SizeDimension { Constant = 0 }
     private enum AxisDimension { Index = 0 }
@@ -78,7 +80,17 @@
     }
     private IEnumerable<string> GetAvailableKeys() {
-      return GetAvailableItems()
-        .SelectMany(n => n.Data.Keys)
-        .Distinct();
+      var collector = new HashSet<string>();
+      GetAvailableKeys(Content, collector);
+      return collector;
+    }
+    private void GetAvailableKeys(RecursiveDataItem node, ISet<string> collector) {
+      foreach (var child in node.Children) {
+        foreach (var key in child.Data.Keys) {
+          collector.Add(node.Name + Separator + key);
+        }
+      }
+
+      foreach (var child in node.Children)
+        GetAvailableKeys(child, collector);
     }
     #endregion
@@ -175,44 +187,73 @@
         var items = GetAvailableItems();
         foreach (var item in items) {
-          var x = GetValue(item, XAxisValue);
-          var y = GetValue(item, YAxisValue);
-          var s = GetValue(item, SizeAxisValue);
-          if (x.HasValue && y.HasValue && s.HasValue) {
-            var dataPoint = new DataPoint(x.Value, new[] { y.Value, s.Value });
-            series.Points.Add(dataPoint);
+          var xs = GetValues(item, XAxisValue).ToList();
+          var ys = GetValues(item, YAxisValue).ToList();
+          var ss = GetValues(item, SizeAxisValue).ToList();
+          if (xs.Count > 0 && ys.Count > 0 && ss.Count == 1) {
+            var s = ss[0];
+            if (xs.Count > 1 && ys.Count > 1) { // index matching
+              for (int i = 0; i < Math.Min(xs.Count, ys.Count); i++)
+                series.Points.Add(new DataPoint(xs[i], new[] { ys[i], s }));
+            } else {
+              foreach (var x in xs)
+                foreach (var y in ys)
+                  series.Points.Add(new DataPoint(x, new[] { y, s }));
+            }
+
           }
         }
       }
     }
-    private double? GetValue(RecursiveDataItem item, string key) {
-      if (item == null || string.IsNullOrEmpty(key))
-        return null;
-
-      if (Enum.IsDefined(typeof(AxisDimension), key)) {
-        var axisDimension = (AxisDimension)Enum.Parse(typeof(AxisDimension), key);
-        return GetValue(item, axisDimension);
-      } else if (Enum.IsDefined(typeof(SizeDimension), key)) {
-        var sizeDimension = (SizeDimension)Enum.Parse(typeof(SizeDimension), key);
-        return GetValue(item, sizeDimension);
-      } else if (item.Data.ContainsKey(key)) {
-        IItem value = item.Data[key];
-        var doubleValue = value as DoubleValue;
-        var intValue = value as IntValue;
-        var timeSpanValue = value as TimeSpanValue;
-        double? ret = null;
-        if (doubleValue != null) {
-          if (!double.IsNaN(doubleValue.Value) && !double.IsInfinity(doubleValue.Value))
-            ret = doubleValue.Value;
-        } else if (intValue != null)
-          ret = intValue.Value;
-        else if (timeSpanValue != null)
-          ret = timeSpanValue.Value.TotalSeconds;
-        else
-          ret = GetCategoricalValue(item, key, value.ToString());
-        return ret;
+
+    private IEnumerable<double> GetValues(RecursiveDataItem parent, string key) {
+      if (parent == null || string.IsNullOrEmpty(key))
+        return Enumerable.Empty<double>();
+      var tokens = key.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries);
+      if (tokens.Length == 2) {
+        var parentKey = tokens[0];
+        var dataKey = tokens[1];
+        if (parent.Name == parentKey) {
+          return parent.Children
+            .Where(child => child.Data.ContainsKey(dataKey))
+            .Select(child => ConvertToDouble(child.Data[dataKey], child, dataKey));
+        }
+        return Enumerable.Empty<double>();
       } else {
-        return null;
-      }
-    }
+        var item = parent;
+        if (item == null || string.IsNullOrEmpty(key))
+          return Enumerable.Empty<double>();
+
+        if (Enum.IsDefined(typeof(AxisDimension), key)) {
+          var axisDimension = (AxisDimension)Enum.Parse(typeof(AxisDimension), key);
+          return GetValue(item, axisDimension).ToEnumerable();
+        } else if (Enum.IsDefined(typeof(SizeDimension), key)) {
+          var sizeDimension = (SizeDimension)Enum.Parse(typeof(SizeDimension), key);
+          return GetValue(item, sizeDimension).ToEnumerable();
+        } else if (item.Data.ContainsKey(key)) {
+          IItem value = item.Data[key];
+          return ConvertToDouble(value, item, key).ToEnumerable();
+        } else {
+          return Enumerable.Empty<double>();
+        }
+      }
+    }
+
+    private double ConvertToDouble(IItem value, RecursiveDataItem item, string key) {
+      var doubleValue = value as DoubleValue;
+      var intValue = value as IntValue;
+      var timeSpanValue = value as TimeSpanValue;
+      double? ret = null;
+      if (doubleValue != null) {
+        if (!double.IsNaN(doubleValue.Value) && !double.IsInfinity(doubleValue.Value))
+          ret = doubleValue.Value;
+      } else if (intValue != null)
+        ret = intValue.Value;
+      else if (timeSpanValue != null)
+        ret = timeSpanValue.Value.TotalSeconds;
+      else
+        ret = GetCategoricalValue(item, key, value.ToString());
+      return ret.Value;
+    }
+
     private double? GetCategoricalValue(RecursiveDataItem item, string key, string value) {
       if (!categoricalMapping.ContainsKey(key)) {
