【发布时间】:2012-02-09 17:41:06
【问题描述】:
我正在努力学习 MVP
它在 ASP.NET 中使用 Web 表单。我有两个用户控件 CurrentTimeView.ascx 和 MonthViewControl.ascx。 CurrentTimeView 显示时间。有一个文本框可以在同一控件中添加天数。新获得的日期称为“结果日期”。当单击按钮添加天数时,会引发一个事件“myBtnAddDaysClickedEvent”。
在 MonthViewControl 上,有一个标签显示“结果日期”的月份。目前我正在为变量“monthValueToPass”设置一个示例值(因为我不知道如何正确执行)。 如何设置monthValueToPass变量的值,使其符合MVP模型?
string monthValueToPass = "TEST";
monthPresenter.SetMonth(monthValueToPass);
期望创建易于进行单元测试且不违反 MVP 架构的 MVP。
注意:虽然这是一个简单的示例,但我希望使用 MVP 和验证机制对 GridView 控件中的数据绑定进行扩展。
注意:视图可以完全独立于演示者吗?
注意:这里每个用户控件都是单独的视图
注意:同一演示者是否可以有多个视图(例如根据不同用户的权限对不同的用户进行不同的控制?)
指南
--完整代码--
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
{
}
}
}
用户控制 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);
}
}
}
用户控制 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 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();
}
}
一些 MVP 讨论:
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 控制
Restrict violation of architecture - asp.net MVP
Control modification in presentation layer
Decoupling the view, presentation and ASP.NET Web Forms 网络表单
【问题讨论】:
-
tl;dr: 如何创建易于进行单元测试且不违反 MVP 架构的 MVP。另外,view可以完全独立于presenter吗?
标签: c# asp.net .net webforms mvp