Index: /trunk/sources/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBProblemView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBProblemView.Designer.cs	(revision 13690)
+++ /trunk/sources/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBProblemView.Designer.cs	(revision 13691)
@@ -52,13 +52,18 @@
       this.parametersTabPage = new System.Windows.Forms.TabPage();
       this.parameterCollectionView = new HeuristicLab.Core.Views.ParameterCollectionView();
+      this.solutionsTabPage = new System.Windows.Forms.TabPage();
       this.flaAnalysisTabPage = new System.Windows.Forms.TabPage();
+      this.flaSplitContainer = new System.Windows.Forms.SplitContainer();
       this.calculateButton = new System.Windows.Forms.Button();
-      this.flaSplitContainer = new System.Windows.Forms.SplitContainer();
       this.characteristicsMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
       this.uploadCharacteristicsButton = new System.Windows.Forms.Button();
       this.downloadCharacteristicsButton = new System.Windows.Forms.Button();
+      this.solutionsViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.refreshSolutionsButton = new System.Windows.Forms.Button();
+      this.uploadSolutionsButton = new System.Windows.Forms.Button();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
       this.parametersTabPage.SuspendLayout();
+      this.solutionsTabPage.SuspendLayout();
       this.flaAnalysisTabPage.SuspendLayout();
       ((System.ComponentModel.ISupportInitialize)(this.flaSplitContainer)).BeginInit();
@@ -135,4 +140,5 @@
             | System.Windows.Forms.AnchorStyles.Right)));
       this.tabControl.Controls.Add(this.parametersTabPage);
+      this.tabControl.Controls.Add(this.solutionsTabPage);
       this.tabControl.Controls.Add(this.flaAnalysisTabPage);
       this.tabControl.Location = new System.Drawing.Point(6, 53);
@@ -148,5 +154,5 @@
       this.parametersTabPage.Name = "parametersTabPage";
       this.parametersTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.parametersTabPage.Size = new System.Drawing.Size(692, 314);
+      this.parametersTabPage.Size = new System.Drawing.Size(728, 447);
       this.parametersTabPage.TabIndex = 0;
       this.parametersTabPage.Text = "Parameters";
@@ -163,6 +169,19 @@
       this.parameterCollectionView.ReadOnly = true;
       this.parameterCollectionView.ShowDetails = true;
-      this.parameterCollectionView.Size = new System.Drawing.Size(686, 308);
+      this.parameterCollectionView.Size = new System.Drawing.Size(722, 441);
       this.parameterCollectionView.TabIndex = 8;
+      // 
+      // solutionsTabPage
+      // 
+      this.solutionsTabPage.Controls.Add(this.uploadSolutionsButton);
+      this.solutionsTabPage.Controls.Add(this.refreshSolutionsButton);
+      this.solutionsTabPage.Controls.Add(this.solutionsViewHost);
+      this.solutionsTabPage.Location = new System.Drawing.Point(4, 22);
+      this.solutionsTabPage.Name = "solutionsTabPage";
+      this.solutionsTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.solutionsTabPage.Size = new System.Drawing.Size(728, 447);
+      this.solutionsTabPage.TabIndex = 3;
+      this.solutionsTabPage.Text = "Solutions";
+      this.solutionsTabPage.UseVisualStyleBackColor = true;
       // 
       // flaAnalysisTabPage
@@ -177,4 +196,24 @@
       this.flaAnalysisTabPage.UseVisualStyleBackColor = true;
       // 
+      // flaSplitContainer
+      // 
+      this.flaSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.flaSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
+      this.flaSplitContainer.Location = new System.Drawing.Point(3, 3);
+      this.flaSplitContainer.Name = "flaSplitContainer";
+      // 
+      // flaSplitContainer.Panel1
+      // 
+      this.flaSplitContainer.Panel1.Controls.Add(this.calculateButton);
+      // 
+      // flaSplitContainer.Panel2
+      // 
+      this.flaSplitContainer.Panel2.Controls.Add(this.characteristicsMatrixView);
+      this.flaSplitContainer.Panel2.Controls.Add(this.uploadCharacteristicsButton);
+      this.flaSplitContainer.Panel2.Controls.Add(this.downloadCharacteristicsButton);
+      this.flaSplitContainer.Size = new System.Drawing.Size(722, 441);
+      this.flaSplitContainer.SplitterDistance = 363;
+      this.flaSplitContainer.TabIndex = 7;
+      // 
       // calculateButton
       // 
@@ -186,24 +225,4 @@
       this.calculateButton.UseVisualStyleBackColor = true;
       this.calculateButton.Click += new System.EventHandler(this.calculateButton_Click);
-      // 
-      // flaSplitContainer
-      // 
-      this.flaSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.flaSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
-      this.flaSplitContainer.Location = new System.Drawing.Point(3, 3);
-      this.flaSplitContainer.Name = "flaSplitContainer";
-      // 
-      // flaSplitContainer.Panel1
-      // 
-      this.flaSplitContainer.Panel1.Controls.Add(this.calculateButton);
-      // 
-      // flaSplitContainer.Panel2
-      // 
-      this.flaSplitContainer.Panel2.Controls.Add(this.characteristicsMatrixView);
-      this.flaSplitContainer.Panel2.Controls.Add(this.uploadCharacteristicsButton);
-      this.flaSplitContainer.Panel2.Controls.Add(this.downloadCharacteristicsButton);
-      this.flaSplitContainer.Size = new System.Drawing.Size(722, 441);
-      this.flaSplitContainer.SplitterDistance = 363;
-      this.flaSplitContainer.TabIndex = 7;
       // 
       // characteristicsMatrixView
@@ -241,4 +260,40 @@
       this.downloadCharacteristicsButton.UseVisualStyleBackColor = true;
       this.downloadCharacteristicsButton.Click += new System.EventHandler(this.downloadCharacteristicsButton_Click);
+      // 
+      // solutionsViewHost
+      // 
+      this.solutionsViewHost.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.solutionsViewHost.Caption = "View";
+      this.solutionsViewHost.Content = null;
+      this.solutionsViewHost.Enabled = false;
+      this.solutionsViewHost.Location = new System.Drawing.Point(0, 35);
+      this.solutionsViewHost.Name = "solutionsViewHost";
+      this.solutionsViewHost.ReadOnly = false;
+      this.solutionsViewHost.Size = new System.Drawing.Size(728, 412);
+      this.solutionsViewHost.TabIndex = 0;
+      this.solutionsViewHost.ViewsLabelVisible = true;
+      this.solutionsViewHost.ViewType = null;
+      // 
+      // refreshSolutionsButton
+      // 
+      this.refreshSolutionsButton.Location = new System.Drawing.Point(6, 6);
+      this.refreshSolutionsButton.Name = "refreshSolutionsButton";
+      this.refreshSolutionsButton.Size = new System.Drawing.Size(26, 23);
+      this.refreshSolutionsButton.TabIndex = 1;
+      this.refreshSolutionsButton.Text = "Refresh";
+      this.refreshSolutionsButton.UseVisualStyleBackColor = true;
+      this.refreshSolutionsButton.Click += new System.EventHandler(this.refreshSolutionsButton_Click);
+      // 
+      // uploadSolutionsButton
+      // 
+      this.uploadSolutionsButton.Location = new System.Drawing.Point(38, 6);
+      this.uploadSolutionsButton.Name = "uploadSolutionsButton";
+      this.uploadSolutionsButton.Size = new System.Drawing.Size(26, 23);
+      this.uploadSolutionsButton.TabIndex = 1;
+      this.uploadSolutionsButton.Text = "Upload";
+      this.uploadSolutionsButton.UseVisualStyleBackColor = true;
+      this.uploadSolutionsButton.Click += new System.EventHandler(this.uploadSolutionsButton_Click);
       // 
       // OKBProblemView
@@ -264,4 +319,5 @@
       this.tabControl.ResumeLayout(false);
       this.parametersTabPage.ResumeLayout(false);
+      this.solutionsTabPage.ResumeLayout(false);
       this.flaAnalysisTabPage.ResumeLayout(false);
       this.flaSplitContainer.Panel1.ResumeLayout(false);
@@ -289,4 +345,8 @@
     private System.Windows.Forms.Button uploadCharacteristicsButton;
     private System.Windows.Forms.Button downloadCharacteristicsButton;
+    private System.Windows.Forms.TabPage solutionsTabPage;
+    private MainForm.WindowsForms.ViewHost solutionsViewHost;
+    private System.Windows.Forms.Button uploadSolutionsButton;
+    private System.Windows.Forms.Button refreshSolutionsButton;
 
 
Index: /trunk/sources/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBProblemView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBProblemView.cs	(revision 13690)
+++ /trunk/sources/HeuristicLab.Clients.OKB.Views/3.3/RunCreation/Views/OKBProblemView.cs	(revision 13691)
@@ -73,4 +73,8 @@
       uploadCharacteristicsButton.Text = string.Empty;
       uploadCharacteristicsButton.Image = VSImageLibrary.PublishToWeb;
+      refreshSolutionsButton.Text = string.Empty;
+      refreshSolutionsButton.Image = VSImageLibrary.Refresh;
+      uploadSolutionsButton.Text = string.Empty;
+      uploadSolutionsButton.Image = VSImageLibrary.PublishToWeb;
     }
 
@@ -93,4 +97,12 @@
       base.RegisterContentEvents();
       Content.ProblemChanged += new EventHandler(Content_ProblemChanged);
+      Content.Solutions.ItemsAdded += SolutionsOnChanged;
+      Content.Solutions.ItemsReplaced += SolutionsOnChanged;
+      Content.Solutions.ItemsRemoved += SolutionsOnChanged;
+      Content.Solutions.CollectionReset += SolutionsOnChanged;
+    }
+
+    private void SolutionsOnChanged(object sender, EventArgs e) {
+      SetEnabledStateOfControls();
     }
 
@@ -100,7 +112,9 @@
         problemComboBox.SelectedIndex = -1;
         parameterCollectionView.Content = null;
+        solutionsViewHost.Content = null;
       } else {
         problemComboBox.SelectedItem = RunCreationClient.Instance.Problems.FirstOrDefault(x => x.Id == Content.ProblemId);
         parameterCollectionView.Content = Content.Parameters;
+        solutionsViewHost.Content = Content.Solutions;
       }
       UpdateCharacteristicCalculators();
@@ -118,4 +132,6 @@
         && characteristicsMatrixView.Content != null && characteristicsMatrixView.Content.Rows > 0;
       calculateButton.Enabled = Content != null && Content.ProblemId != -1 && !Locked && !ReadOnly && calculatorList.CheckedItems.Any();
+      refreshSolutionsButton.Enabled = Content != null && !ReadOnly && !Locked && Content.ProblemId != -1;
+      uploadSolutionsButton.Enabled = Content != null && !ReadOnly && !Locked && Content.ProblemId != -1 && Content.Solutions.Any(x => x.SolutionId == -1);
     }
 
@@ -217,37 +233,40 @@
       }
       var matrix = (characteristicsMatrixView.Content as StringMatrix) ?? (new StringMatrix(results.Count, 3));
-      for (var i = 0; i < matrix.Rows; i++) {
-        Value r;
-        if (results.TryGetValue(matrix[i, 0], out r)) {
-          matrix[i, 1] = r.GetValue();
-          matrix[i, 2] = r.GetType().Name;
-          results.Remove(matrix[i, 0]);
+      try {
+        for (var i = 0; i < matrix.Rows; i++) {
+          Value r;
+          if (results.TryGetValue(matrix[i, 0], out r)) {
+            matrix[i, 1] = r.GetValue();
+            matrix[i, 2] = r.GetType().Name;
+            results.Remove(matrix[i, 0]);
+          }
         }
-      }
-      if (results.Count == 0) return;
-      var resultsList = results.ToList();
-      var counter = resultsList.Count - 1;
-      for (var i = 0; i < matrix.Rows; i++) {
-        if (string.IsNullOrEmpty(matrix[i, 0])) {
-          matrix[i, 0] = resultsList[counter].Key;
-          matrix[i, 1] = resultsList[counter].Value.GetValue();
-          matrix[i, 2] = resultsList[counter].Value.GetType().Name;
-          resultsList.RemoveAt(counter);
-          counter--;
-          if (counter < 0) return;
+        if (results.Count == 0) return;
+        var resultsList = results.ToList();
+        var counter = resultsList.Count - 1;
+        for (var i = 0; i < matrix.Rows; i++) {
+          if (string.IsNullOrEmpty(matrix[i, 0])) {
+            matrix[i, 0] = resultsList[counter].Key;
+            matrix[i, 1] = resultsList[counter].Value.GetValue();
+            matrix[i, 2] = resultsList[counter].Value.GetType().Name;
+            resultsList.RemoveAt(counter);
+            counter--;
+            if (counter < 0) return;
+          }
         }
-      }
-      if (counter >= 0) {
-        ((IStringConvertibleMatrix)matrix).Rows += counter + 1;
-        for (var i = matrix.Rows - 1; counter >= 0; i--) {
-          matrix[i, 0] = resultsList[0].Key;
-          matrix[i, 1] = resultsList[0].Value.GetValue();
-          matrix[i, 2] = resultsList[0].Value.GetType().Name;
-          resultsList.RemoveAt(0);
-          counter--;
+        if (counter >= 0) {
+          ((IStringConvertibleMatrix)matrix).Rows += counter + 1;
+          for (var i = matrix.Rows - 1; counter >= 0; i--) {
+            matrix[i, 0] = resultsList[0].Key;
+            matrix[i, 1] = resultsList[0].Value.GetValue();
+            matrix[i, 2] = resultsList[0].Value.GetType().Name;
+            resultsList.RemoveAt(0);
+            counter--;
+          }
         }
-      }
-      characteristicsMatrixView.Content = matrix;
-      SetEnabledStateOfControls();
+      } finally {
+        characteristicsMatrixView.Content = matrix;
+        SetEnabledStateOfControls();
+      }
     }
     #endregion
@@ -261,4 +280,13 @@
     #endregion
 
+    private void refreshSolutionsButton_Click(object sender, EventArgs e) {
+      Content.RefreshSolutions();
+    }
+
+    private void uploadSolutionsButton_Click(object sender, EventArgs e) {
+      foreach (var solution in Content.Solutions.Where(x => x.SolutionId == -1))
+        solution.Upload();
+    }
+
   }
 }
Index: /trunk/sources/HeuristicLab.Clients.OKB/3.3/HeuristicLab.Clients.OKB-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Clients.OKB/3.3/HeuristicLab.Clients.OKB-3.3.csproj	(revision 13690)
+++ /trunk/sources/HeuristicLab.Clients.OKB/3.3/HeuristicLab.Clients.OKB-3.3.csproj	(revision 13691)
@@ -114,4 +114,5 @@
     <Compile Include="Administration\ServiceClient\ProblemClass.cs" />
     <Compile Include="OKBRoles.cs" />
+    <Compile Include="RunCreation\OKBSolution.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Query\QueryClient.cs" />
@@ -156,4 +157,5 @@
     <Compile Include="RunCreation\OKBProblem.cs" />
     <Compile Include="RunCreation\OKBRun.cs" />
+    <Compile Include="RunCreation\SingleObjectiveOKBSolution.cs" />
     <Compile Include="RunCreation\RunCreationClient.cs" />
     <Compile Include="RunCreation\ServiceClient\Algorithm.cs" />
Index: /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/OKBProblem.cs
===================================================================
--- /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/OKBProblem.cs	(revision 13690)
+++ /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/OKBProblem.cs	(revision 13691)
@@ -29,4 +29,5 @@
 using System.Drawing;
 using System.IO;
+using System.Linq;
 
 namespace HeuristicLab.Clients.OKB.RunCreation {
@@ -63,7 +64,15 @@
             OnOperatorsChanged();
             OnReset();
+
+            solutions.Clear();
           }
         }
       }
+    }
+
+    [Storable]
+    private ItemList<OKBSolution> solutions; 
+    public ItemList<OKBSolution> Solutions {
+      get { return solutions; }
     }
 
@@ -135,4 +144,5 @@
       problemId = original.problemId;
       problem = cloner.Clone(original.problem);
+      solutions = cloner.Clone(original.solutions);
       RegisterProblemEvents();
     }
@@ -142,4 +152,5 @@
       problemId = -1;
       problem = initialProblem;
+      solutions = new ItemList<OKBSolution>();
       RegisterProblemEvents();
     }
@@ -159,4 +170,11 @@
     }
 
+    public void RefreshSolutions() {
+      Solutions.Clear();
+      if (ProblemId != -1) {
+        Solutions.AddRange(RunCreationClient.Instance.GetSolutions(ProblemId).Select(OKBSolution.Convert));
+      }
+    }
+
     public IProblem CloneProblem() {
       return (IProblem)Problem.Clone();
Index: /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/OKBSolution.cs
===================================================================
--- /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/OKBSolution.cs	(revision 13691)
+++ /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/OKBSolution.cs	(revision 13691)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using System;
+
+namespace HeuristicLab.Clients.OKB.RunCreation {
+  [Item("OKB Solution", "")]
+  [StorableClass]
+  public abstract class OKBSolution : Item {
+    [Storable]
+    private long problemId;
+    public long ProblemId {
+      get { return problemId; }
+      protected set { problemId = value; }
+    }
+
+    [Storable]
+    private long solutionId;
+    public long SolutionId {
+      get { return solutionId; }
+      protected set { solutionId = value; }
+    }
+    
+    [Storable]
+    private IItem solution;
+    public IItem Solution {
+      get { return solution; }
+      set {
+        if (solution == value) return;
+        solution = value;
+        OnSolutionChanged();
+      }
+    }
+
+    [StorableConstructor]
+    protected OKBSolution(bool deserializing) : base(deserializing) { }
+    protected OKBSolution(OKBSolution original, Cloner cloner)
+      : base(original, cloner) {
+      problemId = original.problemId;
+      solutionId = original.solutionId;
+      solution = cloner.Clone(original.solution);
+    }
+    protected OKBSolution(long problemId) {
+      this.problemId = problemId;
+      solutionId = -1;
+      solution = null;
+    }
+    protected OKBSolution(Solution sol) {
+      problemId = sol.ProblemId;
+      solutionId = sol.Id;
+    }
+
+    public abstract void Download(long solutionId);
+
+    public abstract void Upload();
+
+    public static OKBSolution Convert(Solution solution) {
+      if (solution is SingleObjectiveSolution) return new SingleObjectiveOKBSolution(solution);
+      throw new ArgumentException("Unknown solution type", "solution");
+    }
+
+    public event EventHandler SolutionChanged;
+    private void OnSolutionChanged() {
+      var handler = SolutionChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/SingleObjectiveOKBSolution.cs
===================================================================
--- /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/SingleObjectiveOKBSolution.cs	(revision 13691)
+++ /trunk/sources/HeuristicLab.Clients.OKB/3.3/RunCreation/SingleObjectiveOKBSolution.cs	(revision 13691)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Persistence.Default.Xml;
+using System;
+using System.IO;
+
+namespace HeuristicLab.Clients.OKB.RunCreation {
+  [Item("OKB Solution (single-objective)", "")]
+  [StorableClass]
+  public sealed class SingleObjectiveOKBSolution : OKBSolution {
+    [Storable]
+    private double quality;
+    public double Quality {
+      get { return quality; }
+      set {
+        if (quality == value) return;
+        quality = value;
+        OnQualityChanged();
+      }
+    }
+
+    [StorableConstructor]
+    private SingleObjectiveOKBSolution(bool deserializing) : base(deserializing) { }
+    private SingleObjectiveOKBSolution(SingleObjectiveOKBSolution original, Cloner cloner)
+      : base(original, cloner) {
+      quality = original.quality;
+    }
+    public SingleObjectiveOKBSolution(long problemId) : base(problemId) {
+      quality = double.NaN;
+    }
+    public SingleObjectiveOKBSolution(Solution solution) : base(solution) {
+      var soSolution = solution as SingleObjectiveSolution;
+      if (soSolution == null) throw new ArgumentException("Solution is not of type SingleObjectiveSolution", "solution");
+      Quality = soSolution.Quality;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SingleObjectiveOKBSolution(this, cloner);
+    }
+
+    public override void Download(long solutionId) {
+      if (SolutionId == solutionId) return;
+      byte[] solutionData = RunCreationClient.Instance.GetSolutionData(solutionId);
+      using (var stream = new MemoryStream(solutionData)) {
+        Solution = XmlParser.Deserialize<IItem>(stream);
+        SolutionId = solutionId;
+      }
+      var sol = RunCreationClient.Instance.GetSolution(solutionId);
+      ProblemId = sol.ProblemId;
+      var soSol = sol as SingleObjectiveSolution;
+      if (soSol == null) throw new InvalidOperationException(string.Format("Solution with id {0} is not a single-objective solution.", solutionId));
+      Quality = soSol.Quality;
+    }
+
+    public override void Upload() {
+      if (SolutionId != -1) throw new InvalidOperationException("Solution exists already.");
+      using (var stream = new MemoryStream()) {
+        if (Solution != null) XmlGenerator.Serialize(Solution, stream);
+        SolutionId = RunCreationClient.Instance.AddSolution(
+          new SingleObjectiveSolution() {
+            ProblemId = ProblemId,
+            Quality = Quality,
+            DataType = Solution != null ? new DataType() {
+              Name = Solution.GetType().Name,
+              TypeName = Solution.GetType().FullName
+            } : null
+          }, stream.ToArray());
+      }
+    }
+
+    public event EventHandler QualityChanged;
+    private void OnQualityChanged() {
+      var handler = QualityChanged;
+      if  (handler != null) handler(this, EventArgs.Empty);
+    }
+  }
+}
