Index: /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs	(revision 9848)
+++ /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs	(revision 9849)
@@ -29,5 +29,5 @@
   public partial class ProgressView : AsynchronousContentView {
     private const int DefaultCancelTimeoutMs = 3000;
-    private ContentView parentView;
+    private readonly IView parentView;
 
     [Category("Custom"), Description("The time that the process is allowed to exit.")]
@@ -41,4 +41,10 @@
     }
 
+    private Control Control {
+      get { return (Control)parentView; }
+    }
+
+    public bool DisposeOnFinish { get; set; }
+
     public ProgressView() {
       InitializeComponent();
@@ -48,12 +54,19 @@
       Content = progress;
     }
-    public ProgressView(ContentView parentView)
+    public ProgressView(IView parentView)
       : this() {
       if (parentView == null) throw new ArgumentNullException("parentView", "The parent view is null.");
+      if (!(parentView is Control)) throw new ArgumentException("The parent view is not a control.", "parentView");
       this.parentView = parentView;
     }
-    public ProgressView(ContentView parentView, IProgress progress)
+    public ProgressView(IView parentView, IProgress progress)
       : this(parentView) {
       Content = progress;
+    }
+
+    public static ProgressView Attach(IView parentView, IProgress progress, bool disposeOnFinish = false) {
+      return new ProgressView(parentView, progress) {
+        DisposeOnFinish = disposeOnFinish
+      };
     }
 
@@ -94,12 +107,12 @@
       else {
         if (parentView != null) {
-          this.Left = (parentView.ClientRectangle.Width / 2) - (this.Width / 2);
-          this.Top = (parentView.ClientRectangle.Height / 2) - (this.Height / 2);
+          this.Left = (Control.ClientRectangle.Width / 2) - (this.Width / 2);
+          this.Top = (Control.ClientRectangle.Height / 2) - (this.Height / 2);
           this.Anchor = AnchorStyles.None;
 
           LockBackground();
 
-          if (!parentView.Controls.Contains(this))
-            parentView.Controls.Add(this);
+          if (!Control.Controls.Contains(this))
+            Control.Controls.Add(this);
 
           BringToFront();
@@ -115,6 +128,6 @@
       else {
         if (parentView != null) {
-          if (parentView.Controls.Contains(this))
-            parentView.Controls.Remove(this);
+          if (Control.Controls.Contains(this))
+            Control.Controls.Remove(this);
 
           UnlockBackground();
@@ -133,9 +146,15 @@
 
     private void Content_ProgressStateChanged(object sender, EventArgs e) {
-      if (Content.ProgressState == ProgressState.Finished
-        || Content.ProgressState == ProgressState.Canceled)
-        HideProgress();
-      if (Content.ProgressState == ProgressState.Started)
-        ShowProgress();
+      switch (Content.ProgressState) {
+        case ProgressState.Finished:
+          HideProgress();
+          if (DisposeOnFinish) {
+            Content = null;
+            Dispose();
+          }
+          break;
+        case ProgressState.Canceled: HideProgress(); break;
+        case ProgressState.Started: ShowProgress(); break;
+      }
     }
 
@@ -148,8 +167,6 @@
         Invoke((Action)LockBackground);
       } else {
-        parentView.Locked = true;
-        parentView.ReadOnly = true;
-        Locked = false;
-        ReadOnly = false;
+        parentView.Enabled = false;
+        Enabled = true;
       }
     }
@@ -158,8 +175,6 @@
       if (InvokeRequired) Invoke((Action)UnlockBackground);
       else {
-        parentView.Locked = false;
-        parentView.ReadOnly = false;
-        Locked = true;
-        ReadOnly = true;
+        parentView.Enabled = true;
+        Enabled = false;
       }
     }
Index: /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/MainForms/MainForm.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/MainForms/MainForm.cs	(revision 9848)
+++ /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/MainForms/MainForm.cs	(revision 9849)
@@ -30,4 +30,6 @@
 namespace HeuristicLab.MainForm.WindowsForms {
   public partial class MainForm : Form, IMainForm {
+    private readonly Dictionary<IContent, IProgress> contentProgressLookup;
+    private readonly Dictionary<IView, IProgress> viewProgressLookup;
     private bool initialized;
     private int appStartingCursors;
@@ -39,4 +41,6 @@
       this.views = new Dictionary<IView, Form>();
       this.userInterfaceItems = new List<IUserInterfaceItem>();
+      this.contentProgressLookup = new Dictionary<IContent, IProgress>();
+      this.viewProgressLookup = new Dictionary<IView, IProgress>();
       this.initialized = false;
       this.showContentInViewHost = false;
@@ -343,4 +347,59 @@
         CloseView(view, closeReason);
     }
+
+    /// <summary>
+    /// Adds a <see cref="ProgressView"/> to the <see cref="ContentView"/>s showing the specified content.
+    /// </summary>
+    public void AddOperationProgressToContent(IContent content, IProgress progress, bool addToObjectGraphObjects = true) {
+      if (contentProgressLookup.ContainsKey(content))
+        throw new ArgumentException("A progress is already registered for the specified content.", "content");
+
+      var contentViews = Enumerable.Empty<IContentView>();
+      if (addToObjectGraphObjects) {
+        var containedObjects = content.GetObjectGraphObjects();
+        contentViews = views.Keys.OfType<IContentView>().Where(v => containedObjects.Contains(v.Content));
+      } else
+        contentViews = views.Keys.OfType<IContentView>().Where(v => v.Content == content);
+
+      foreach (var contentView in contentViews)
+        ProgressView.Attach(contentView, progress, true);
+
+      contentProgressLookup[content] = progress;
+    }
+
+    /// <summary>
+    /// Adds a <see cref="ProgressView"/> to the specified view.
+    /// </summary>
+    public void AddOperationProgressToView(IView view, Progress progress) {
+      if (viewProgressLookup.ContainsKey(view))
+        throw new ArgumentException("A progress is already registered for the specified view.", "view");
+
+      ProgressView.Attach(view, progress, true);
+      viewProgressLookup[view] = progress;
+    }
+
+    /// <summary>
+    /// Removes an existing <see cref="ProgressView"/> from the <see cref="ContentView"/>s showing the specified content.
+    /// </summary>
+    public void RemoveOperationProgressFromContent(IContent content) {
+      IProgress progress;
+      if (!contentProgressLookup.TryGetValue(content, out progress))
+        throw new ArgumentException("No progress is registered for the specified content.", "content");
+
+      progress.Finish();
+      contentProgressLookup.Remove(content);
+    }
+
+    /// <summary>
+    /// Removes an existing <see cref="ProgressView"/> from the specified view.
+    /// </summary>
+    public void RemoveOperationProgressFromView(IView view) {
+      IProgress progress;
+      if (!viewProgressLookup.TryGetValue(view, out progress))
+        throw new ArgumentException("No progress is registered for the specified view.", "view");
+
+      progress.Finish();
+      viewProgressLookup.Remove(view);
+    }
     #endregion
 
Index: /trunk/sources/HeuristicLab.MainForm/3.3/Interfaces/IProgress.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm/3.3/Interfaces/IProgress.cs	(revision 9848)
+++ /trunk/sources/HeuristicLab.MainForm/3.3/Interfaces/IProgress.cs	(revision 9849)
@@ -28,18 +28,18 @@
   public interface IProgress : IContent {
     /// <summary>
-    /// Gets the currently associated status text with the progress.
+    /// Gets or sets the currently associated status text with the progress.
     /// </summary>
-    string Status { get; }
+    string Status { get; set; }
     /// <summary>
-    /// Gets the currently associated progress value in the range (0;1].
+    /// Gets or sets the currently associated progress value in the range (0;1].
     ///  Values outside this range are permitted and need to be handled in some feasible manner.
     /// </summary>
-    double ProgressValue { get; }
+    double ProgressValue { get; set; }
     /// <summary>
-    /// Gets the current state of the progress. Every progress starts in state
+    /// Gets or sets the current state of the progress. Every progress starts in state
     /// Started and then becomes either Canceled or Finished.
     /// If it is reused it may be Started again.
     /// </summary>
-    ProgressState ProgressState { get; }
+    ProgressState ProgressState { get; set; }
     /// <summary>
     /// Returns whether the operation can be canceled or not.
@@ -56,4 +56,8 @@
     /// <param name="timeoutMs">The operation is given a certain timeout to cancel. If the operation doesn't cancel in this time it will be forcibly closed.</param>
     void Cancel(int timeoutMs);
+    /// <summary>
+    /// Sets the ProgressValue to 1 and the ProgressState to Finished.
+    /// </summary>
+    void Finish();
 
     /// <summary>
Index: /trunk/sources/HeuristicLab.MainForm/3.3/Progress.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm/3.3/Progress.cs	(revision 9848)
+++ /trunk/sources/HeuristicLab.MainForm/3.3/Progress.cs	(revision 9849)
@@ -86,7 +86,4 @@
     }
 
-    /// <summary>
-    /// Sets the ProgressValue to 1 and the ProgressState to Finished.
-    /// </summary>
     public void Finish() {
       if (ProgressValue != 1.0) ProgressValue = 1.0;
Index: /trunk/sources/HeuristicLab.Optimizer/3.3/FileManager.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimizer/3.3/FileManager.cs	(revision 9848)
+++ /trunk/sources/HeuristicLab.Optimizer/3.3/FileManager.cs	(revision 9849)
@@ -22,5 +22,5 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
+using System.IO;
 using System.Windows.Forms;
 using HeuristicLab.Common;
@@ -98,5 +98,5 @@
           SaveAs(view);
         else {
-          ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).SetAppStartingCursor();
+          MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().SetAppStartingCursor();
           SetEnabledStateOfContentViews(content, false);
           ContentManager.SaveAsync(content, content.Filename, true, SavingCompleted);
@@ -123,5 +123,5 @@
 
         if (saveFileDialog.ShowDialog() == DialogResult.OK) {
-          ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).SetAppStartingCursor();
+          MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().SetAppStartingCursor();
           SetEnabledStateOfContentViews(content, false);
           if (saveFileDialog.FilterIndex == 1) {
@@ -135,5 +135,4 @@
     private static void SavingCompleted(IStorableContent content, Exception error) {
       try {
-        SetEnabledStateOfContentViews(content, true);
         if (error != null) throw error;
         MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().UpdateTitle();
@@ -143,5 +142,6 @@
       }
       finally {
-        ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).ResetAppStartingCursor();
+        SetEnabledStateOfContentViews(content, true);
+        MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().ResetAppStartingCursor();
       }
     }
@@ -152,6 +152,8 @@
       // removed the InvokeRequired check because of Mono
       mainForm.Invoke((Action)delegate {
-        var views = MainFormManager.MainForm.Views.OfType<IContentView>().Where(v => v.Content == content).ToList();
-        views.ForEach(v => v.Enabled = enabled);
+        if (enabled)
+          mainForm.RemoveOperationProgressFromContent(content);
+        else
+          mainForm.AddOperationProgressToContent(content, new Progress(string.Format("Saving file \"{0}\"...", Path.GetFileName(content.Filename))));
       });
       #endregion
