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
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
最新评论