簡體   English   中英

事件冒泡和MVP:ASP.NET

[英]Event Bubbling and MVP: ASP.NET

我正在嘗試學習MVP

它在ASP.NET中使用Web表單。 我有兩個用戶控件CurrentTimeView.ascx和MonthViewControl.ascx。 CurrentTimeView顯示時間。 有一個文本框可在同一控件中添加日期。 新獲得的日期稱為“結果日期”。 單擊按鈕添加天數時,將引發一個事件“ myBtnAddDaysClickedEvent”。

在MonthViewControl上,有一個標簽顯示“結果日期”的月份。 目前,我正在為變量“ monthValueToPass”設置一個樣本值(因為我不知道如何正確執行)。 如何設置monthValueToPass變量的值以使其符合MVP模型?

string monthValueToPass = "TEST";
monthPresenter.SetMonth(monthValueToPass);

期望創建易於執行單元測試並且不違反MVP架構的MVP。

注意:盡管這是一個簡單的示例,但我期望使用MVP和驗證機制對GridView控件中的數據綁定有答案。

注意:視圖可以完全獨立於演示者嗎?

注意:每個用戶控件在這里都是單獨的視圖

注意:同一演示者是否可以有多個視圖(例如,基於其權限的不同用戶的不同控件?)

指南

  1. 模型視圖演示者-准則

-完整代碼-

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討論:

模型視圖演示者-准則

在MVP中寫驗證的位置

MVP-視圖應該能夠直接調用presenter方法還是應該始終引發事件?

MVP事件或財產

MVP中的模型-事件

MVP-主持人應該使用會話嗎?

為什么在大多數ASP.NET MVP實現中,Presenter都附加到View事件,而不是View調用Presenter方法?

公開方法或訂閱View事件

MVP模式,對演示者有多少視圖?

MVP和UserControls以及調用

ASP.NET Web窗體-模型視圖演示者和用戶控件控件

限制違反體系結構-ASP.NET MVP

表示層中的控件修改

將視圖,演示文稿和ASP.NET Web窗體的 Web窗體分離

TLDR代碼。

這就是我要做的。 您說同一頁面上有2個控件。 因此,可以由帶有TimeVM和MonthVM的引用(成員)的ContainerVM來提供服務。

  1. 每當您執行操作時,TimeVM都會更新后備屬性ResultantDate。
  2. ContainerVM已訂閱TimeVM.ResultantDate的屬性更改的通知。 每當收到更改通知時,它將調用MonthVM.SetMonth()

現在可以在不使用任何視圖的情況下(僅在演示者級別)對其進行測試。

感謝您的輸入。 我提到了MVP快速入門http://msdn.microsoft.com/en-us/library/ff650240.aspx Model can raise events 我認為,我應該采用這種方法。 任何想法都歡迎。

另外,我已經發布了http://forums.asp.net/t/1760921.aspx/1?Model+View+Presenter+Guidelines來收集有關MVP的一般規則。

引用

開發可以與View和Model進行通信的Presenter。 演示者可能僅具有視圖界面的知識。 即使具體視圖發生變化,也不會影響演示者。

在具體視圖中,控件的事件處理程序將僅調用演示者方法或引發演示者將已訂閱的事件。 不應以具體的視圖編寫表示規則/邏輯。

演示者應僅具有模型的接口對象; 不是具體的模型。 這是為了便於單元測試

視圖可以引用業務實體。 但是,不應編寫與實體對象相關聯的邏輯。 它可能只是將實體對象傳遞給演示者。

視圖接口應該是一個抽象。 它不應具有任何控件或System.Web參考。 具體而言,接口定義的方法除外。

“模型”從不了解具體視圖以及界面視圖

“模型”可以定義和引發事件。 演示者可以訂閱這些由模型引發的事件。

演示者中的公共方法應該是無參數的。 視圖對象應僅訪問演示者的無參數方法。 另一個選項是視圖可以定義演示者可以訂閱的事件。 無論哪種方式,都不應傳遞參數。

由於模型具有所有必需的值(要存儲回數據庫中),因此無需(大部分時間)將任何值從視圖傳遞給模型。 例如,當在下拉列表中選擇一項時,只需將控件的當前索引傳遞給模型。 然后模型知道如何獲取相應的域值。 在這種情況下,視圖無需將任何內容傳遞給演示者。 演示者知道如何從視圖中獲取價值。

視圖可以直接使用模型(不使用演示者)。 例如ObjectDataSource的SelectMethod。 但是控制器從不知道具體視圖和接口視圖。

演示者引用視圖接口,而不是視圖的具體實現。 這允許您在運行單元測試時用模擬視圖替換實際視圖。

我沒有使用ASP.net的經驗,但是我想我遵循您嘗試做的事情的要旨。

似乎通過為單個UI元素創建演示者,可以與演示者精通一個層次。 在這種情況下,月份和時間。 我將其更多地視為ShowTime時期。 ShowTime可以顯示月份和時間。

將此與MVP一起使用。 然后,您將需要該頁面將實現的IShowTimeView。 (不是控件)。 然后編寫一個使用IShowTimeView發送和檢索值的ShowTimePresenter。

您將讓ShowTime實現IShowTimeView接口。 它將諸如時間,AddDay事件和月份之類的項目往返於頁面上的實際控件。

因此,如果我了解您的文章。 事件的順序將是這樣的。

用戶輸入要添加的天數。 用戶單擊添加天數“添加天數”會觸發該事件,該事件會在“當前”上調用一個方法來添加天數。 演示者中添加天數的方法將進行計算和其他所需的步驟。 然后,add days方法將使用Presenter中的View指針來告訴視圖以計算的值更新Month。 然后,視圖將采用在控件上設置正確屬性的計算值。

要進行單元測試,您需要制作一個實現IShowTimeView的模擬對象,並使用它代替實際的頁面對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM