Model View Presenter (MVP)

Three components

  • View - UI / how the information is displayed. Fires events to the presenter

  • Model - data/business entities

  • Presenter -


The main difference between this and the Model View Controller is that the presenter refers back to the view
There are two variations:
Passive View - reduces the behaviour of the UI to the absolute minimum by using a Presenter that handles user events and updates the view
Supervising Controller - handles input responses and more complex view logic


Exactly how you structure the code is up to you and there are endless variations.
The layout and structure defined below is designed to help you understand how this pattern actually works.



Creating the View

1) Create a new folder in your project called Form1

2) Add a Windows Form "Form1_View" to the Form1 folder.

This will create a partial class that inherits from the System.Forms.Form class.


3) Add an Interface above this partial class called "IForm1_View".

public interface IForm1_View 
{
   string Property_Caption { set; }
}

public partial class Form1_View : Form
{
    public Form1_View()
    {
        InitializeComponent();
    }
}


4) Add this interface to the partial class declaration

Make the following changes to the Form1_View class

public partial class Form1_View : Form, IForm1_View 
{
    private MVP.ChangeRequestEvents _changerequestedevents = null;
    private bool _fireevents = false;

    //-----------------------------------------------------------------------
    public Form1_View()
    {
        InitializeComponent();
        this._changerequestedevents = new MVP.ChangeRequestEvents(this);
    }
    //-----------------------------------------------------------------------
   public string Property_Caption
   {
      set { this.text = value; }
   }
    //-----------------------------------------------------------------------
    public void RegisterChangeRequestListener<T>(string PropertyName,
        System.EventHandler<MVP.PropertyChangeRequestEventArgs<T>> handler)
    {
        this._changerequestedevents.RegisterListener<T>(PropertyName, handler);
    }
    //-----------------------------------------------------------------------
    public void UnRegisterChangeRequestListener<T>(string PropertyName,
        System.EventHandler<MVP.PropertyChangeRequestEventArgs<T>> handler)
    {
        this._changerequestedevents.UnRegisterListener<T>(PropertyName, handler);
    }
    //-----------------------------------------------------------------------
    public void FireChangeRequest(string PropertyName, string requestedValue)
    {
        if (this._changerequestedevents != null)
        {
            this._changerequestedevents.Fire(PropertyName, requestedValue);
        }
    }


Creating the Model

5) Add a class to the Form1 folder called Form1_Model.

Make the following changes to this code.

public interface IForm1_Model 
{
}

public class Form1_Model : System.ComponentModel.INotifyPropertyChanged, IForm1_Model
{
    private event System.ComponentModel.PropertyChangedEventHandler _eventpropertychanged;

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged
    {
        add { this._eventpropertychanged += value; }
        remove { this._eventpropertychanged -= value; }
    }
}


Creating the Presenter

6) Add a class to the Form1 folder called "Form1_Presenter"

Make the following changes to this class

public class Form1_Presenter : PassiveView<Form1_Model, Form1_View> 
{
    public Form1_Presenter(Form1_Model MyModel, Form1_View MyView)
    {
        base.Initialize(MyModel, MyView);
    }

    protected override void WireEvents()
    {
        base._view.RegisterChangeRequestListener(this.View.GetType().Name,
             new System.EventHandler<MVP.PropertyChangeRequestEventArgs<string>> (this.Method_OnEvent));
    }

    protected override void UnwireEvents()
    {
        base._view.UnRegisterChangeRequestListener(this.View.GetType().Name,
             new System.EventHandler<MVP.PropertyChangeRequestEventArgs<string>> (this.Method_OnEvent));
    }

    private void Method_OnEvent(object Sender, MVP.PropertyChangeRequestEventArgs<string> args)
    {
        switch (args.RequestedValue.ToLower())
        {
        }
    }



Create the Model View Presenter base classes

7) Create another folder to your project called "MVP"

8) Add a class to the MVP folder called "PropertyChangeRequestEventArgs"

Make the following changes to this class

public class PropertyChangeRequestEventArgs<T> : System.EventArgs 
{
    public T RequestedValue { get; set; }

    public PropertyChangeRequestEventArgs(T value)
    {
        this.RequestedValue = value;
    }
}


9) Add a class to the MVP folder called "PassiveView"

Make the following changes to this class

    public abstract class PassiveView<TModel, TView> : System.IDisposable 
    {
        protected TView View { get; set; }
        protected TModel Model { get; set; }

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

        public virtual void Initialize(TModel MyModel, TView MyView)
        {
            if (this.Model != null || this.View != null)
            {
                UnwireEvents();
            }

            this.Model = MyModel;
            this.View = MyView;

            WireEvents();
        }

        public void Dispose()
        {
            UnwireEvents();
        }
    }


10) Add a class to the MVP folder called "EventHolder".

Make the following changes to this class.

    public class EventHolder<T> 
    {
        private event System.EventHandler<PropertyChangeRequestEventArgs<T>> _onevent;

        public void Fire(object Sender, T RequestedValue)
        {
            if (this._onevent != null)
            {
                this._onevent(Sender, new PropertyChangeRequestEventArgs<T>(RequestedValue));
            }
        }

        public event EventHandler<PropertyChangeRequestEventArgs<T>> OnEvent
        {
            add { this._onevent += value; }
            remove { this._onevent -= value; }
        }
    }


11) Add a class to the MVP folder called "ChangeRequestEvents".

Make the following changes to this class.

    public class ChangeRequestEvents 
    {
        private System.Collections.Generic.Dictionary<System.Type, System.Collections.Generic.Dictionary<string, object>> _pool;
        private object _sender;

        public ChangeRequestEvents(object Sender)
        {
            this._pool = new System.Collections.Generic.Dictionary<System.Type, System.Collections.Generic.Dictionary<string, object>>();
            this._sender = Sender;
        }

        public void RegisterListener<T>(string PropertyName, System.EventHandler<PropertyChangeRequestEventArgs<T>> handler)
        {
            if (!this._pool.ContainsKey(typeof(T)))
            {
                this._pool.Add(typeof(T), new System.Collections.Generic.Dictionary<string, object>());
            }

            System.Collections.Generic.Dictionary<string, object> EventsDictionary = this._pool[typeof(T)];

            if (!EventsDictionary.ContainsKey(PropertyName))
            {
                EventsDictionary.Add(PropertyName, new EventHolder<T>());
            }

            EventHolder<T> holder = EventsDictionary[PropertyName] as EventHolder<T>;
            holder.OnEvent += handler;
        }

        public void UnRegisterListener<T>(string PropertyName, System.EventHandler<PropertyChangeRequestEventArgs<T>> handler)
        {
            if (!this._pool.ContainsKey(typeof(T)))
            {
                return;
            }

            System.Collections.Generic.Dictionary<string, object> EventsDictionary = this._pool[typeof(T)];

            if (!EventsDictionary.ContainsKey(PropertyName))
            {
                return;
            }

            EventHolder<T> holder = EventsDictionary[PropertyName] as EventHolder<T>;
            holder.OnEvent -= handler;
        }

        public void Fire<T>(string PropertyName, T requestedValue)
        {
            if (!this._pool.ContainsKey(typeof(T)))
            {
                return;
            }

            System.Collections.Generic.Dictionary<string, object> EventsDictionary = this._pool[typeof(T)];

            if (!EventsDictionary.ContainsKey(PropertyName))
            {
                return;
            }

            EventHolder<T> holder = EventsDictionary[PropertyName] as EventHolder<T>;
            holder.Fire(this._sender, requestedValue);
        }
    }


Displaying Form

Create the view and the model before creating the presenter.

MyForm oView = new MyForm(); 
MyModel oModel = new MyModel();
oView.Property_Caption = "text";
MyPresenter oPresenter = new MyPresenter(oModel, oView);
oView.ShowDialog();



© 2017 Better Solutions Limited. All Rights Reserved. © 2017 Better Solutions Limited

PrevNext