I am trying to learn MVP
It is using web forms in ASP.NET. I have two user controls CurrentTimeView.ascx and MonthViewControl.ascx. The CurrentTimeView displayes time. There is a textbox to add days in the same control. The newly got date is called “resultant date”. When the button is clicked for add days, an event is raised “myBtnAddDaysClickedEvent“.
On the MonthViewControl, there is a label that shows the month of the “resultant date”. At present I am setting a sample value for the variable “monthValueToPass” (since I don’t know how to do it properly). How do I set the value for monthValueToPass variable to make it comply with MVP model?
string monthValueToPass = "TEST";
monthPresenter.SetMonth(monthValueToPass);
The expectation is to create MVP that is easy to do Unit Testing and does not violate MVP architecure.
Note: Though this is a simple example, I am expecting an answer scalablt to databinding in GridView control using MVP and validation mechanisms.
Note: Can view be totally independant of presenter?
Note: Each user control is separate views here
Note: Can there be multiple views for same presenter (like different controls for various users based on thier permisssion?)
GUIDELINES
--COMPLETE CODE--
using System;
public interface ICurrentTimeView
{
//Property of View
DateTime CurrentTime
{
set;
}
//Method of View
void AttachPresenter(CurrentTimePresenter presenter);
}
using System;
public interface IMonthView
{
//Property of View
string MonthName
{
set;
}
//Method of View
//View interface knows the presenter
void AttachPresenter(MonthPresenter presenter);
}
using System;
public class CurrentTimePresenter
{
private ICurrentTimeView view;
//Constructor for prsenter
public CurrentTimePresenter(ICurrentTimeView inputView)
{
if (inputView == null)
{
throw new ArgumentNullException("view may not be null");
}
}
this.view = inputView;
}
//Method defined in Presenter
public void SetCurrentTime(bool isPostBack)
{
if (!isPostBack)
{
view.CurrentTime = DateTime.Now;
}
}
//Method defined in Presenter
public void AddDays(string daysUnparsed, bool isPageValid)
{
if (isPageValid)
{
view.CurrentTime = DateTime.Now.AddDays(double.Parse(daysUnparsed));
}
}
using System;
public class MonthPresenter
{
private IMonthView monthView;
//Constructor for prsenter
public MonthPresenter(IMonthView inputView)
{
if (inputView == null)
{
throw new ArgumentNullException("view may not be null");
}
this.monthView = inputView;
}
//Method defined in Presenter
//How does presenter decides the required value.
public void SetMonth(string monthValueInput)
{
if (!String.IsNullOrEmpty(monthValueInput))
{
monthView.MonthName = monthValueInput;
}
else
{
}
}
}
User Control 1
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CurrentTimeView.ascx.cs" Inherits="Views_CurrentTimeView" %>
<asp:Label id="lblMessage" runat="server" /><br />
<asp:Label id="lblCurrentTime" runat="server" /><br />
<br />
<asp:TextBox id="txtNumberOfDays" runat="server" />
<asp:Button id="btnAddDays" Text="Add Days" runat="server" OnClick="btnAddDays_OnClick" ValidationGroup="AddDays" />
using System;
using System.Web.UI;
public partial class Views_CurrentTimeView : UserControl, ICurrentTimeView
{
//1. User control has no method other than view defined method for attaching presenter
//2. Properties has only set method
private CurrentTimePresenter presenter;
// Delegate
public delegate void OnAddDaysClickedDelegate(string strValue);
// Event
public event OnAddDaysClickedDelegate myBtnAddDaysClickedEvent;
//Provision for getting the presenter in User Control from aspx page.
public void AttachPresenter(CurrentTimePresenter presenter)
{
if (presenter == null)
{
throw new ArgumentNullException("presenter may not be null");
}
this.presenter = presenter;
}
//Implement View's Property
public DateTime CurrentTime
{
set
{
//During set of the property, set the control's value
lblCurrentTime.Text = value.ToString();
}
}
//Event Handler in User Control
protected void btnAddDays_OnClick(object sender, EventArgs e)
{
if (presenter == null)
{
throw new FieldAccessException("presenter null");
}
//Ask presenter to do its functionality
presenter.AddDays(txtNumberOfDays.Text, Page.IsValid);
//Raise event
if (myBtnAddDaysClickedEvent != null)
{
myBtnAddDaysClickedEvent(string.Empty);
}
}
}
User Control 2
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MonthViewControl.ascx.cs" Inherits="Views_MonthViewControl" %>
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Views_MonthViewControl : System.Web.UI.UserControl, IMonthView
{
//1. User control has no method other than view defined method for attaching presenter
//2. Properties has only set method
private MonthPresenter presenter;
//Provision for gettng the presenter in User Control from aspx page.
public void AttachPresenter(MonthPresenter presenter)
{
if (presenter == null)
{
throw new ArgumentNullException("presenter may not be null");
}
this.presenter = presenter;
}
//Implement View's Property
public string MonthName
{
set
{
//During set of the popert, set the control's value
lblMonth.Text = value.ToString();
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
ASPX Page
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ShowMeTheTime.aspx.cs" Inherits="ShowTime" %>
<%@ Register TagPrefix="mvpProject" TagName="CurrentTimeView" Src="Views/CurrentTimeView.ascx" %>
<%@ Register TagPrefix="month" TagName="MonthView" Src="Views/MonthViewControl.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>PAGE TITLE </title>
</head>
<body>
<form id="form1" runat="server">
<mvpProject:CurrentTimeView id="ucCtrlcurrentTimeView" runat="server"
/>
<br />
<br />
<month:MonthView id="ucCtrlMonthView" runat="server" />
</form>
</body>
</html>
using System;
using System.Web.UI;
public partial class ShowTime : Page
{
CurrentTimePresenter currentTimePresenter;
MonthPresenter monthPresenter;
protected void Page_Load(object sender, EventArgs e)
{
HelperInitCurrentTimeView();
HelperInitMonth();
}
private void HelperInitMonth()
{
//Create presenter
monthPresenter = new MonthPresenter(ucCtrlMonthView);
//Pass the presenter object to user control
ucCtrlMonthView.AttachPresenter(monthPresenter);
}
private void HelperInitCurrentTimeView()
{
//Cretes presenter by passing view(user control) to presenter.
//User control has implemented IView
currentTimePresenter = new CurrentTimePresenter(ucCtrlcurrentTimeView);
//Pass the presenter object to user control
ucCtrlcurrentTimeView.AttachPresenter(currentTimePresenter);
//Call the presenter action to load time in user control.
currentTimePresenter.SetCurrentTime(Page.IsPostBack);
//Event described in User Control ???? Subsribe for it.
ucCtrlcurrentTimeView.myBtnAddDaysClickedEvent += new Views_CurrentTimeView.OnAddDaysClickedDelegate(CurrentTimeViewControl_AddButtonClicked_MainPageHandler);
}
void CurrentTimeViewControl_AddButtonClicked_MainPageHandler(string strValue)
{
string monthValue = "l";
monthPresenter.SetMonth("SAMPLE VALUE");
//myGridCntrl.CurentCharacter = theLetterCtrl.SelectedLetter;
//myGridCntrl.LoadGridValues();
}
}
Some MVP discussions:
Model View Presenter - Guidelines
In MVP where to write validations
MVP - Should views be able to call presenter methods directly or should they always raise events?
MVP - Should the Presenter use Session?
Public Methods or subscribe to View events
MVP pattern, how many views to a presenter?
MVP and UserControls and invocation
ASP.NET Web Forms - Model View Presenter and user controls controls
Restrict violation of architecture - asp.net MVP
Control modification in presentation layer
Decoupling the view, presentation and ASP.NET Web Forms web-forms