天天看點

譯】使用自定義ViewHelper來簡化Asp.net MVC view的開發------part4

接上篇,我們下面通過HtmlFiledSet helper來展示何時使用EndView():

    如果你用Asp.net已經有一段時間了,那使用Html.BeginForm helper來建立HTML form标簽的方式會讓你覺得有點怪.當你建立一個新的Asp.net mvc項目後,在View裡的ChangePassword.aspx會預設被建立,這個頁面使用了Html.BeginForm helper,下面是使用這個helper的代碼段:

<% using (Html.BeginForm()) { %> 

    <div> 

        <fieldset> 

            <legend>Account Information</legend> 

            <p> 

                <label for="currentPassword">Current password:</label> 

                <%= Html.Password("currentPassword") %> 

                <%= Html.ValidationMessage("currentPassword") %> 

            </p> 

                <label for="newPassword">New password:</label> 

                <%= Html.Password("newPassword") %> 

                <%= Html.ValidationMessage("newPassword") %> 

            <p>                 <label for="confirmPassword">Confirm new password:</label> 

                <%= Html.Password("confirmPassword") %> 

                <%= Html.ValidationMessage("confirmPassword") %> 

                <input type="submit" value="Change Password" /> 

        </fieldset> 

    </div> 

<% } %> 

上面代碼中你會發現Html.BeginForm的使用和<%=Html.Password(“currentPassword”) %>的使用不盡相同,也就是Html.BeginForm在using語句中被調用,這點很有意思,讓我先來看看上面代碼段生成後的Html,如下:

<form  

  action="/Account/LogOn?ReturnUrl=%2fAccount%2fChangePassword"  

  method="post"> 

  <div> 

    <fieldset> 

      <legend>Account Information</legend> 

      <p> 

        <label for="username">Username:</label> 

        <input id="username" name="username" type="text" value="" />   

      </p> 

        <label for="password">Password:</label> 

        <input id="password" name="password" type="password" />   

        <input id="rememberMe" name="rememberMe" type="checkbox" value="true" /> 

        <input name="rememberMe" type="hidden" value="false" /> 

        <label class="inline" for="rememberMe">Remember me?</label> 

        <input type="submit" value="Log On" /> 

    </fieldset> 

  </div> 

</form> 

比較<%= Html.Password("currentPassword") %> 語句和Html.BeginForm所生成的HTML代碼你會發現password那段僅僅僅僅将調用password擴充方法變成對應的Html,而BeginForm調用HTML擴充方法來注入form的開始标簽,<form…>,和using語句結束時(“}”)注入标簽<./form>.這種方式十分友善,因為我們可以一方面使用view helper建立合适的form标簽,另一方面在form标簽内插入任何我們想插入的html.這種方法的工作原理是當你調用Html.BeginForm方法并傳回MvcForm類型的對象,這個對象在using語句中是以當對象被回收(譯者按:也就是Dispose)的時候,也就是執行到結尾的”<% } %>”時,關閉标簽</form>将會被寫入到View中.下面是Dispose方法的實作:

public void Dispose() { 

    Dispose(true /* disposing */); 

    GC.SuppressFinalize(this); 

protected virtual void Dispose(bool disposing) { 

    if (!_disposed) { 

        _disposed = true; 

        _httpResponse.Write("</form>"); 

    } 

我們用相似的方法來實作HtmlFieldSet:

從這篇文章附帶的代碼中有一個”DetailsClassic.aspx”頁面中,一些字段包含于fieldset元素中,具體代碼如下:

<fieldset class="details-field-group" name="Details"> 

  <legend>Details</legend> 

  <ol> 

    <li> 

      <label for="FirstName">FirstName</label> 

      <span id="FirstName"> 

        <%= Html.Encode(Model.FirstName) %></span>  

    </li> 

      <label for="LastName">LastName</label> 

      <span id="LastName"><%= Html.Encode(Model.LastName) %></span> 

      <label for="Email">Email</label> 

      <span id="Email"><%= Html.Encode(Model.Email) %></span> 

      <label for="Phone">Phone</label> 

      <span id="Phone"><%= Html.Encode(Model.Phone) %></span> 

      <label for="Gender">Gender</label> 

      <span id="Gender"><%= Html.Encode(Model.Gender) %></span> 

  </ol> 

</fieldset> 

如果能用一個view helper來建立下面所有的html标簽,那會惬意很多:

fieldset的開始标記

legend标簽

ol的開始标簽

ol的結束标簽

fieldset的結束标簽

如果能用view helper來處理這些,那上面那段代碼無疑會簡單很多,尤其再加上使用Html.Text标簽來代替上面的text域。讓我們開始做到這一點,首先建立一個實作IViewObject接口的類,命名為HtmlFieldSet類并繼承與AbstractHtmlViewObject,整個類的代碼附下:

public class HtmlFieldset : AbstractHtmlViewObject 

    private readonly string mTitle; 

    public HtmlFieldset( 

        ViewRequestContext requestContext, string name,  

        string title, object attributes) 

        : base(requestContext, name) 

    { 

        mTitle = title; 

        Attributes = attributes; 

    private TagBuilder FieldsetTag { get; set; } 

    private TagBuilder OlTag { get; set; } 

    public override void StartView() 

        HttpResponseBase httpResponse = RequestContext.HttpResponse; 

        FieldsetTag = new TagBuilder("fieldset"); 

        // apply any Attributes passed in 

        if (Attributes != null) 

        { 

            FieldsetTag.MergeAttributes(new RouteValueDictionary(Attributes)); 

        }  

        // The Name property should override any passed into the Attributes 

        FieldsetTag.MergeAttribute("name", Name, true); 

        httpResponse.Write(FieldsetTag.ToString(TagRenderMode.StartTag)); 

        if (!string.IsNullOrEmpty(mTitle)) 

            TagBuilder legendTag = new TagBuilder("legend"); 

            legendTag.SetInnerText(mTitle); 

            httpResponse.Write(legendTag.ToString(TagRenderMode.Normal)); 

        } 

        OlTag = new TagBuilder("ol"); 

        httpResponse.Write(OlTag.ToString(TagRenderMode.StartTag)); 

    public override void EndView() 

        httpResponse.Write(OlTag.ToString(TagRenderMode.EndTag)); 

        httpResponse.Write(FieldsetTag.ToString(TagRenderMode.EndTag)); 

這個類的實作和其它的view對象沒什麼不同,除了EndView方法,在這裡我們需要EndView方法來生成必須的結束标記。當然我們也可以使用EndView來生成任何需要的HTML,在這裡我們僅是用它生成結束标記。

-------------------------------------------

待續…

原文連結:http://mvcviewhelpers.codeplex.com/

translated by CareySon

分類: Asp.net MVC

本文轉自CareySon部落格園部落格,原文連結:http://www.cnblogs.com/CareySon/archive/2010/01/07/1640987.html,如需轉載請自行聯系原作者

繼續閱讀