Index: branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/HeuristicLab.DataPreprocessing-3.3.csproj
===================================================================
--- branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/HeuristicLab.DataPreprocessing-3.3.csproj	(revision 10549)
+++ branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/HeuristicLab.DataPreprocessing-3.3.csproj	(revision 10550)
@@ -247,4 +247,9 @@
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Views\DataPreprocessingView.resx">
+      <DependentUpon>DataPreprocessingView.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
Index: branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Implementations/PreprocessingData.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Implementations/PreprocessingData.cs	(revision 10549)
+++ branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Implementations/PreprocessingData.cs	(revision 10550)
@@ -30,7 +30,24 @@
 
 namespace HeuristicLab.DataPreprocessing {
+
+  internal class PDSnapshot {
+    public IDictionary<int, IList> VariableValues { get; set; }
+
+    public IList<string> VariableNames { get; set; }
+
+    public double TrainingToTestRatio { get; set; }
+
+    public DataPreprocessingChangedEventType ChangedType { get; set; }
+
+    public int ChangedColumn { get; set; }
+
+    public int ChangedRow { get; set; }
+  }
+
   [Item("PreprocessingData", "Represents data used for preprocessing.")]
   public class PreprocessingData : NamedItem, IPreprocessingData {
 
+    private const int MAX_UNDO_DEPTH = 5;
+
     private IDictionary<int, IList> variableValues;
 
@@ -38,12 +55,13 @@
 
     private double trainingToTestRatio;
+
+    private IList<PDSnapshot> undoHistory;
 
     private PreprocessingData(PreprocessingData original, Cloner cloner)
       : base(original, cloner) {
-      variableValues = new Dictionary<int, IList>(original.variableValues);
-      for (int i = 0; i < variableValues.Count; i++)
-        variableValues[i] = new ArrayList(original.variableValues[i]);
+      variableValues = CopyVariableValues(original.variableValues);
       variableNames = new List<string>(original.variableNames);
       trainingToTestRatio = original.trainingToTestRatio;
+      undoHistory = new List<PDSnapshot>();
     }
 
@@ -71,4 +89,5 @@
 
       trainingToTestRatio = (double)problemData.TrainingPartition.Size / Math.Max(problemData.Dataset.Rows, double.Epsilon);
+      undoHistory = new List<PDSnapshot>();
     }
 
@@ -81,4 +100,35 @@
     }
 
+    private IDictionary<int, IList> CopyVariableValues(IDictionary<int, IList> original) {
+      var copy = new Dictionary<int, IList>(variableValues);
+      for (int i = 0; i < original.Count; i++) {
+        if (variableValues[i] is IList<double>) {
+          copy[i] = new List<double>((IList<double>)variableValues[i]);
+        } else if (variableValues[i] is IList<DateTime>) {
+          copy[i] = new List<DateTime>((IList<DateTime>)variableValues[i]);
+        } else if (variableValues[i] is IList<string>) {
+          copy[i] = new List<string>((IList<string>)variableValues[i]);
+        } else {
+          throw new NotImplementedException("The Type is not Supported");
+        }
+      }
+      return copy;
+    }
+
+    private void SaveSnapshot(DataPreprocessingChangedEventType changedType, int column, int row) {
+      PDSnapshot currentSnapshot = new PDSnapshot();
+      currentSnapshot.VariableValues = CopyVariableValues(variableValues);
+      currentSnapshot.VariableNames = new List<string>(variableNames);
+      currentSnapshot.TrainingToTestRatio = trainingToTestRatio;
+      currentSnapshot.ChangedType = changedType;
+      currentSnapshot.ChangedColumn = column;
+      currentSnapshot.ChangedRow = row;
+
+      if (undoHistory.Count >= MAX_UNDO_DEPTH)
+        undoHistory.RemoveAt(0);
+
+      undoHistory.Add(currentSnapshot);
+    }
+
     #region NamedItem abstract Member Implementations
 
@@ -96,5 +146,6 @@
 
 
-    public void SetCell<T>(int columnIndex, int rowIndex, T value) {    // Undo-sensitive
+    public void SetCell<T>(int columnIndex, int rowIndex, T value) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
       variableValues[columnIndex][rowIndex] = value;
       OnChanged(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
@@ -116,6 +167,7 @@
     }
 
-    public void SetValues<T>(int columnIndex, IList<T> values) {    // Undo-sensitive
+    public void SetValues<T>(int columnIndex, IList<T> values) {
       if (IsType<T>(columnIndex)) {
+        SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
         variableValues[columnIndex] = (IList)values;
       } else {
@@ -125,5 +177,6 @@
     }
 
-    public void InsertRow(int rowIndex) {    // Undo-sensitive
+    public void InsertRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
       foreach (IList column in variableValues.Values) {
         Type type = column.GetType().GetGenericArguments()[0];
@@ -133,5 +186,6 @@
     }
 
-    public void DeleteRow(int rowIndex) {    // Undo-sensitive
+    public void DeleteRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
       foreach (IList column in variableValues.Values) {
         column.RemoveAt(rowIndex);
@@ -140,5 +194,6 @@
     }
 
-    public void InsertColumn<T>(string variableName, int columnIndex) {    // Undo-sensitive
+    public void InsertColumn<T>(string variableName, int columnIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
       variableValues.Add(columnIndex, new List<T>(Rows));
       variableNames.Insert(columnIndex, variableName);
@@ -146,5 +201,6 @@
     }
 
-    public void DeleteColumn(int columnIndex) {    // Undo-sensitive
+    public void DeleteColumn(int columnIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
       variableValues.Remove(columnIndex);
       variableNames.RemoveAt(columnIndex);
@@ -203,9 +259,18 @@
 
     public bool IsUndoAvailable {
-      get { throw new NotImplementedException(); }
+      get { return undoHistory.Count > 0; }
     }
 
     public void Undo() {
-      throw new NotImplementedException();
+      if (IsUndoAvailable) {
+        PDSnapshot previousSnapshot = undoHistory[undoHistory.Count - 1];
+        variableValues = previousSnapshot.VariableValues;
+        variableNames = previousSnapshot.VariableNames;
+        trainingToTestRatio = previousSnapshot.TrainingToTestRatio;
+        undoHistory.Remove(previousSnapshot);
+        OnChanged(previousSnapshot.ChangedType,
+          previousSnapshot.ChangedColumn,
+          previousSnapshot.ChangedRow);
+      }
     }
 
Index: branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Views/DataPreprocessingView.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Views/DataPreprocessingView.cs	(revision 10549)
+++ branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Views/DataPreprocessingView.cs	(revision 10550)
@@ -140,4 +140,8 @@
       MainFormManager.MainForm.ShowContent(item);
     }
+
+    private void undoButton_Click(object sender, EventArgs e) {
+      Content.Data.Undo();
+    }
   }
 }
Index: branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Views/DataPreprocessingView.designer.cs
===================================================================
--- branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Views/DataPreprocessingView.designer.cs	(revision 10549)
+++ branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Views/DataPreprocessingView.designer.cs	(revision 10550)
@@ -45,4 +45,5 @@
     private void InitializeComponent() {
       this.components = new System.ComponentModel.Container();
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DataPreprocessingView));
       this.splitContainer1 = new System.Windows.Forms.SplitContainer();
       this.undoButton = new System.Windows.Forms.Button();
@@ -81,5 +82,5 @@
       // undoButton
       // 
-      this.undoButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Undo;
+      this.undoButton.Image = ((System.Drawing.Image)(resources.GetObject("undoButton.Image")));
       this.undoButton.Location = new System.Drawing.Point(72, 14);
       this.undoButton.Name = "undoButton";
@@ -88,8 +89,9 @@
       this.toolTip.SetToolTip(this.undoButton, "Undo");
       this.undoButton.UseVisualStyleBackColor = true;
+      this.undoButton.Click += new System.EventHandler(this.undoButton_Click);
       // 
       // applyInNewTabButton
       // 
-      this.applyInNewTabButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Play;
+      this.applyInNewTabButton.Image = ((System.Drawing.Image)(resources.GetObject("applyInNewTabButton.Image")));
       this.applyInNewTabButton.Location = new System.Drawing.Point(42, 14);
       this.applyInNewTabButton.Name = "applyInNewTabButton";
@@ -102,5 +104,5 @@
       // exportProblemButton
       // 
-      this.exportProblemButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Save;
+      this.exportProblemButton.Image = ((System.Drawing.Image)(resources.GetObject("exportProblemButton.Image")));
       this.exportProblemButton.Location = new System.Drawing.Point(12, 14);
       this.exportProblemButton.Name = "exportProblemButton";
@@ -113,6 +115,6 @@
       // contentListView
       // 
-      this.contentListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.contentListView.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.contentListView.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
@@ -128,6 +130,6 @@
       // viewHost
       // 
-      this.viewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.viewHost.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.viewHost.Caption = "View";
