Wednesday, November 01, 2006

Composite UI Application Block Model View Presenter

Model View Presenter
is a design pattern support by CAB and the Smart Client Software Factory (SCSF).

A View is a SmartPart.

The Presenter calls methods of the View to update the information the View displays. The View should expose its methods to the Presenter through an Interface. The Presenter stores a reference to the View's interface.

In my examples I have updated UserButton and added IUserButton and UserButtonPresenter.

Here is IUserButton.cs:


using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace CABTestOne
{
public interface IUserButton
{
void SetColor( Color color );
}
}


Here is the new UserButton.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.EventBroker;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
[SmartPart]
public partial class UserButton : UserControl, IUserButton
{
public MyMessagePublisher publisher;
protected UserButtonPresenter _userButtonPresenter;

public UserButton( )
{
InitializeComponent( );
}

private void button1_MouseClick( object sender, MouseEventArgs e )
{
_userButtonPresenter.UserButtonClicked( sender, e );
publisher.UserButtonClicked( sender, e );
}

[CreateNew]
public UserButtonPresenter userButtonPresenter
{
set
{
_userButtonPresenter = value;
_userButtonPresenter.userButton = this;
}
}

public void SetColor( Color color )
{
this.button1.BackColor = color;
}
}
}

Here is the new UserButtonPresenter.cs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.EventBroker;

namespace CABTestOne
{
public class UserButtonPresenter : IDisposable
{
protected WorkItem _workItem;
protected IUserButton _userButton;

~UserButtonPresenter( )
{
Dispose(false);
}


public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}


protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if( _workItem != null )
{
_workItem.Items.Remove( this );
}
}
}

[ServiceDependency]
public WorkItem workItem
{
set
{
_workItem = value;
}
}

public IUserButton userButton
{
set
{
_userButton = value;
}
}

[EventPublication( "topic://CABTestOne/UserButtonClick", PublicationScope.Global )]
public event EventHandler UserButtonClick;

public void UserButtonClicked( object sender, MouseEventArgs e )
{
_userButton.SetColor( System.Drawing.Color.Blue );

if( UserButtonClick != null )
{
UserButtonClick( this, null );
}
}
}
}
[ServiceDependency] tells the CAB framework to get the WorkItem from the collection of services maintained by CAB. The UserButtonPresenter needs the WorkItem in order to enhance the dispose method to remove itself from the WorkItem's Item collection.

How did I know to modify the Dispose methods to remove the Presenter? I looked at lots of code I found on the net.

Listening to a PodCast I learned that a WorkItem is two things.
  1. Scoping Container
  2. Lifetime Manager
[CreateNew] is an attribute added to a property in the UserButton. The CreateNew tells the dependency injector of COB to instantiate a new UserButtonPresenter.

I moved the Event Publisher inside of the UserButton and put it in the UserButtonPresenter. I am not sure if it "should" be there it just seemed like the thing to do.

In the UserButtonPresenter when the UserButtonClicked method is invoked it does two things:
  1. Sets the color of the UserButton
  2. Publishes the UserButtonClick event.

After I completed these code changes I then installed and started using the Smart Client Software Factory. I used the Guidance Package that was installed into Visual Studio 2005 to create a new solution that uses CAB and the MVP pattern. The guidance package auto generated all of the code. Granted the auto generated code included things I had not yet studied but I found that I have turned the learning curve and have enough foundation and a feel for CAB that I am able to understand the auto generated code. So, this will probably be my last blog entry on the Composite UI Application Block. I have a lot to learn still but I can see enough now that I don't feel like I am lost in the dark.

By the way, I have been learning CAB in this fashion because it is part of an approach I am working on called Experience Driven Development (EDD) and has a fundamental practices Design by Use and Software Reconn.

2 comments:

Anonymous said...

Extermely Helpful for novices like me

Anonymous said...

Extermely useful for novices like me :0)