derivative:Implementing the Passive View -- a Derivative of the Model-View-Control

Introduction.

A while ago I wrote an article about the MVC pattern and just recently received a request for an example closer to a real-world implementation so I thought I would share the approach I have used in live projects.

There are a bunch flavors of MVC. Here is an article by Martin Fowler about some of the differences if you really want to dig in. For this article, we'll be discussing building a passive view to keep the model and the view as "dumb" as possible and avoid any dependencies between two. The idea being that all of our implementation should lie in the control and not in the UI (the view).

So let's get started....

Part I. A Control Base Class

Since we'll be coding many different types of controllers for different views and models, it makes sense to pull the common functionality out into a base class and have the supertypes handle the parts that are different. Using this technique we come up with what is called the "template pattern" for all you design pattern junkies out there. The controller will need to keep references to both the view and the model and we'll be using an event driven architecture to wire things up. What will happen, is the control will listen to events from the view and the model and be responsible for updating the view if the model changes and updating the model with change requests from the view.

A control will need references to both the view and the model and will also need a bunch of event handlers for notifications received from both the view and the model. With our control base class, we don't know what the specific events will be to wire up from the concrete implementations of the view and model, so we'll create a few abstract methods as placeholders. We'll eventually need to connect the three pieces (the model, view and control). We'll do this using an Initialize() method that will be responsible for wiring all the connections between the control and it's model and view. Just to keep things clean, we'll make this class disposable in order to unwire all the events if the object is explicitly disposed to avoid any unexpected behavior.

public abstract class MvcControlBase<TModel, TView> : IDisposable
{
#region Member Variables

protected TView m_view;
protected TModel m_model;

#endregion

#region Abstract Methods

protected abstract void WireEvents();
protected abstract void UnwireEvents();
protected abstract void SetViewState();

#endregion

#region Methods

public virtual void Initialize(TModel model, TView view)
{
if (m_model != null || m_view != null)
UnwireEvents();

m_model = model;
m_view = view;

SetViewState();
WireEvents();
}

#endregion

#region Properties

public TModel Model { get { return m_model; } }
public TView View { get { return m_view; } }

#endregion

#region IDisposable Members

public void Dispose()
{
UnwireEvents();
}

#endregion
}

Part II. The Control-View Wiring.

We need an object to carry the message from the view to the control when the view is requesting a change to a property of the model. In order to do this, we'll be using a custom class derived from EventArgs that will carry the new value that has been requested by the view.

public class PropertyChangeRequestEventArgs<T>:EventArgs
{
public PropertyChangeRequestEventArgs(T pRequestedValue)
{
RequestedValue = pRequestedValue;
}

public T RequestedValue { get; set; }
}

Because we'll have a separate event for each property the view is expressing _disibledevent=MsoBodyText>Happy coding

Tags:  derivativefree derivativeaction derivativeworks derivative

延伸阅读

最新评论

发表评论