讓WEB FORM更像WINDOWS FORM: 控制表單事件

來源:互聯網
上載者:User

[按]
你可能會誤解本文標題:讓WEB FORM 更像WINDOWS FORM。 你也許會把本文當作是討論應用程式介面. 其實本文討論的是ASP.NET表現層設計。  也許會給你一點啟示:如何設計邏輯隔離良好的、更容易設計和管理的應用程式。作者是一個偏向於應用的開發人員,因此可能在某些方面涉論不深,希望可以與有更多想法的朋友交流。作者的電子郵件xujian(a)nwpu.edu.cn

[引言]
在項目設計和實施的過程中,我經常再想,既然我們必須給使用者以樣式美觀並且易用的使用者介面,就應該好好設計表現層的UI邏輯。或者想辦法把商務邏輯、系統邏輯、和UI邏輯隔離得更好。使介面相關元素得到最大程度的重用和最大的靈活性。

本文的核心論述對象是ASCX(ASP.NET User Controls)。這裡我們把ASCX比作WIN32應用程式的”表單(FORM)“。我們知道,設計WINDOWS應用程式的時候,不管使用什麼開發工具,使用者介面的主要構成元素是“表單”,我們預先設計好承擔不同任務的表單,然後在適當的時候把他們彈出來,任務完成後把他們關掉。這樣就基本完成了使用者介面的流程式控制制。

而ASCX是類似可嵌入到網頁中的UI單元。我們可以通過編寫HTML來開發一個ASCX。這隻是ASP.NET架構所提供的一種機制。我們可以把ASCX做為FORM,像操作WINDOWS FORMS一樣操作網頁中的ASCX,來完成我們的UI邏輯。

由於ASCX可以嵌入頁面中,這就使得最大程度重用頁面構圖提供了可能性。我們可以把ASPX頁面當作ASCX的容器。ASPX僅包含UI邏輯。更複雜的業務上的邏輯由ASCX承擔。甚至ASCX僅承載資料。(在我的實際經驗中,我總是設計兩類ASCX。一類是資料類,僅以一定格式顯示資料,不承擔商務邏輯;另外一種是事務型,用來完成某種操作。)ASPX控制其中的各個ASCX互動顯示隱藏,由此完成流程式控制制。

實現的障礙在哪裡?提供ASCX的主要目的是隱藏其中的邏輯,並且提供一定程度上的重用性。但是ASCX內部的邏輯並不能和其容器直接交流。也就是說ASCX對外界是一無所知的。承載ASCX的容器(可能是一個ASPX頁面或者另一個ASCX)可以很方便的控制他的顯示,隱藏,但是容器卻不知道什麼時候關閉他。在流程完成後,ASCX無法直接調用容器的方法是自己關掉。

關鍵性的技巧就是讓ASCX可以向外引發事件。只要ASCX需要變動自己的UI狀態,就以一定的事件通知容器。而不用管容器如何處理。而容器可以很容易捕獲控制項的事件而最初相應處理。這樣就給我們提供了一種指導性的模式。

作者的設計。一般而言, 我給表現層的ASPX和ASCX都至少抽象一個基類。基類裡包含所有ASCX都需要的內容。有安全方面的,有系統配置方面的。對於本文所論述的內容,我使所有ASCX都可以引發三種事件,分別代表ASCX生命週期的各個階段,他們是:

MissionStart:事務開始,代表控制項最初狀態。
MissionAbort:事務中止,使用者的操作取消。需要返回原介面。
MissionEnd:事務結束, 使用者的操作完成,需要進一步處理。

這三個事件都沒有任何參數,他們僅僅包含了介面邏輯,和商務邏輯沒有關係。 這樣我們可以在使用者沒有進行有結果的操作,並且需要返回原介面時引發MissionAbort事件,在使用者操作完成,需要進一步處理時引發MissionEnd事件。(MissionStart我還從來沒有應用到, 但我想預留這麼一個事件是必要的。)

[有關原始碼]
以下原始碼摘自UserControlBase.cs 該類繼承自System.System.Web.UI.UserControl
  /// <summary>
  /// 關鍵系統事件: 事務開始. ASCX生命週期開始.
  /// </summary>
  public event System.EventHandler MissionStart;

  /// <summary>
  /// 關鍵系統事件: 事務中止. 未進行到事件最終狀態. ASCX關閉但操作未完成.
  /// </summary>
  public event System.EventHandler MissionAbort;

  /// <summary>
  /// 關鍵系統事件: 事務完成. 既定操作完成. ASCX被關閉, 通知容器向下進行.
  /// </summary>
  public event System.EventHandler MissionEnd;

  /// <summary>
  /// 引發MissionStart事件
  /// </summary>
  protected void RaiseMissionStart()
  {
   if(this.MissionStart != null)
   {
    this.MissionStart(this, new System.EventArgs());
   }
  }

  /// <summary>
  /// 引發MissionAbort事件
  /// </summary>
  protected void RaiseMissionAbort()
  {
   if(this.MissionAbort != null)
   {
    this.MissionAbort(this, new System.EventArgs());
   }
  }

  /// <summary>
  /// 引發MissionEnd事件
  /// </summary>
  protected void RaiseMissionEnd()
  {
   if(this.MissionEnd != null)
   {
    this.MissionEnd(this, new System.EventArgs());
   }
  }
ASCX需要從此基類派生. 例如:
public class ComplexSearch : XxxXxx.YyyYyy.UserControlBase
{
...
}

上述ASCX是一個做組合查詢的UI. 有一個“取消“命令按鈕. 我們在取消按鈕的Click事件上做如下命令
This.RaiseMissionAbort();

之後容器捕獲該事件, 在private void InitializeComponent()方法中加上:
this.XxxXxxxx.MissionAbort += new EventHandler(AttributeInsert_MissionAbort);

(注意:以上代碼是+=以後的部分IDE可以自動為你完成. 並且自動產生複合編碼約定的方法名):

  private void XxxXxxxx_MissionAbort(object sender, EventArgs e)
  {
   ///...(處理過程)
  }

以上僅僅是基類相關事件的定義以及應用範例. 實際情況也複雜不到哪裡去. 不過除了這些之外, 作者所開發的項目中, 幾乎每個ASCX都有著異常豐富的特性. 有著較高的可重用性/靈活性和獨立性.

[幾點與主題無關的原則]
1. 盡量抽象一些公用特性到基類
2. 盡量分離邏輯. 公開足夠的特性(Properties), 方法, 事件.
3. 設計上多用一天, 可以減少幾天的編碼及維護工作量. 並且可為後繼的工作帶來便利.

[結束]
本著拋磚引玉的想法,本文僅僅討論了給ASCX加上三個事件。想法簡單明晰,但在一定程度上反映了”架構“上的一些思想。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.