BugFix - View not disposing

Topics: CAB & Smart Client Software Factory
Dec 9, 2007 at 5:16 AM
SCSF May 2007

I found issues where the View is still not being disposed properly when the presenter is disposed.

When the view is not properly disposed you will not get proper behavior from the WorkItemController's ShowViewInWorkspace method; the view will still be present in the WorkItem.SmartParts list not permitting a new view and presenter to be instantiated.

I updated the Presenter.cs file's dispose method as shown below:
        /// <summary>
        /// Called when the object is being disposed or finalized.
        /// </summary>
        /// <param name="disposing">True when the object is being disposed (and therefore can
        /// access managed members); false when the object is being finalized without first
        /// having been disposed (and therefore can only touch unmanaged members).</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_workItem != null)
                {
                    // WK.2007.12.08 - View object not being released
                    // Remove view from _workItem collection
                    if (this.View != null)
                        _workItem.Items.Remove(this.View);
                    _workItem.Items.Remove(this);
                }
            }
        }
Dec 11, 2007 at 4:24 PM
Hi

Although your code properly sets that when the Presenter is disposed the View will be disposed as well, the IWorkspace.Close(smartPart) method does not call the Dispose() method of the Presenter so the View won’t get disposed either (the same happens to the WorkItem.SmartParts.Remove(smartPart) method).

You may find handy these links regarding the view disposal:
Please let me know if this helps.

Ignacio Baumann Fonay
http://staff.southworks.net/blogs/ibaumann/
Dec 15, 2007 at 7:34 PM


Although your code properly sets that when the Presenter is disposed the View will be disposed as well, the IWorkspace.Close(smartPart) method does not call the Dispose() method of the Presenter so the View won’t get disposed either (the same happens to the WorkItem.SmartParts.Remove(smartPart) method).
://staff.southworks.net/blogs/ibaumann/]


The Smart Client Software Factory is based on the Model-View-Presenter pattern; it is the View's responsibility to instantiate and dispose of the presenter. This eliminates the "cancel" issue noted in your first referenced link, i.e., if the user cancels closing the view then it will not dispose of the presenter, likewise if the view's closing is not cancelled the presenter will be disposed accordingly.

There is a series of bugs in the SCSF Guidance package recipes that can cause some confusion - for example in the Foundation Module's "add view with presenter" (which I use to create a test harness UI to the data services). The view's designer.cs code-behind file's Dispose method will incorrectly look as follows:
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
           base.Dispose(disposing);
        }

Where the Busines Module "add view with presenter" guidance package recipe will correctly setup the View's designer.cs as follows:
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_presenter != null)
                    _presenter.Dispose();
 
                if (components != null)
                    components.Dispose();
            }
 
            base.Dispose(disposing);
        }

If you'll ensure that the View's Dispose method properly disposes the presenter as shown above, the Presenter.cs will ensure the workItem collection is properly updated to reflect the system state.

What further confused matters was if you used the ShowViewInWorkspace<TView>(string viewId, string workspaceName) in your Module Controller (so that it will only allow the form to be loaded once). Without the noted fix in the Presenter.cs file, line 4 below will always find the view and return a reference to it; since it was disposed the next time you attempt to load the form it will be blank.

To confuse matters more... This is assuming of course that you fixed line 10 - Like line 6 it should have a reference to the viewId that is provided as a parameter. Without this fix the viewId will not be attached to the view and it will never be found on line 4 resulting in NEW views being created each time.

Excerpt from WorkItemController.cs follows:
 1        protected virtual TView ShowViewInWorkspace<TView>(string viewId, string workspaceName)
 2       {
 3           TView view = default(TView);
 4           if (WorkItem.SmartParts.Contains(viewId))
 5           {
 6               view = WorkItem.SmartParts.Get<TView>(viewId);
 7           }
 8           else
 9           {
10                view = WorkItem.SmartParts.AddNew<TView>();   <== Current (wrong)
10                view = WorkItem.SmartParts.AddNew<TView>(viewId);   <<== Correct
11           }
12          WorkItem.Workspaces[workspaceName].Show(view);
13          return view;
14      }

The suggested changes in Presenter.cs and WorkItemController.cs will provide you a predictable environment for your views.