2011-04-13 115 views
6

我現在有一個div容器都在我的表單的輸入域,類似於:剃刀基本類型/與「使用」關鍵字模板化的剃刀代表

<div class="ux-single-field ui-widget-content ui-corner-all"> 
    @Html.LabelFor(m => m.Name) 
    @Html.TextBoxFor(m => m.Name) 
</div> 

我想知道我怎麼會

@using (Html.BeginForm()) { 
} 

我可以簡單地總結我的元素,如:

此使用 templated razor delegate(或 any other trick),所以就像我們用封裝0
+0

我可以問你要實現的目標是什麼? - 你想Html.ContentField()生成一個div嗎? – ebb 2011-04-13 13:09:40

+0

@ebb是的。上面的div。 – rebelliard 2011-04-13 13:14:13

回答

7

使用Razor視圖引擎,這裏是什麼在起作用:

namespace MyProject.Web.Helpers.Extensions 
{ 
    public static class LayoutExtensions 
    { 
     public static ContentField BeginContentField(this HtmlHelper htmlHelper) 
     { 
      return FormHelper(htmlHelper, new RouteValueDictionary()); 
     } 

     public static ContentField BeginContentField(this HtmlHelper htmlHelper, RouteValueDictionary htmlAttributes) 
     { 
      return FormHelper(htmlHelper, htmlAttributes); 
     } 

     public static void EndContentField(this HtmlHelper htmlHelper) 
     { 
      htmlHelper.ViewContext.Writer.Write("</div>"); 
     } 

     private static ContentField FormHelper(this HtmlHelper htmlHelper, IDictionary<string, object> htmlAttributes) 
     { 
      TagBuilder tagBuilder = new TagBuilder("div"); 
      tagBuilder.MergeAttributes(htmlAttributes); 
      tagBuilder.MergeAttribute("class", "ux-single-field ui-widget-content ui-corner-all"); 

      htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag)); 
      return new ContentField(htmlHelper.ViewContext.Writer); 
     } 
    } 

    public class ContentField : IDisposable 
    { 
     private bool _disposed; 
     private readonly TextWriter _writer; 

     public ContentField(TextWriter writer) 
     { 
      if (writer == null) 
       throw new ArgumentNullException("writer"); 

      _writer = writer; 
     } 

     [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] 
     public void Dispose() 
     { 
      Dispose(true /* disposing */); 
      GC.SuppressFinalize(this); 
     } 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!_disposed) 
      { 
       _disposed = true; 

       _writer.Write("</div>"); 
      } 
     } 

     public void EndForm() 
     { 
      Dispose(true); 
     } 
    } 
} 

FYI:使用舊引擎ASPX,here's how to do it

1

讓我們來看看(或猜測)Html.BeginForm()做什麼。從「渲染的角度來看」,它通常只是將起始表單標籤呈現到html輸出中。它是一次性的,因爲在這種情況下,它知道表單的內部html內容何時完成呈現,並且可以在其Dispose()方法中呈現結束</form>標記。通過所有這些,您首先會打開form標記,而不是您希望的自定義​​html內容,然後是結束標記。結果 - 您會在輸出中獲得完整的HTML表單。

<form> 

...contents(Result of Html.TextBoxFor, etc. helpers) 

</form> 

我認爲你的情況最好像表單一樣。目前我沒有足夠的時間來編寫完整的代碼,但是如果您通過查看源代碼(Thanks @druttka)反射器(如果您有舊版本或購買的許可證)或http://wiki.sharpdevelop.net/ilspy.ashx(請參閱FormExtensions.BeginForm)和上面的解釋,你可以從開始的地方得到重點。從BeginForm方法中刪除不必要的代碼,創建您的MvcContentField:IDisposable類而不是MvcForm,將其上的Dispose()更改爲呈現結束div標記,您將得到完全所需的內容。

+2

不需要Reflector或ILSpy; MVC3源代碼可以免費獲得http://aspnet.codeplex.com/releases/view/58781檢查Html文件夾/名稱空間下的MvcForm.cs和FormExtensions.cs文件。 – 2011-04-13 13:22:23

+0

Hmmkay。我會研究它,並試圖找出它。會及時向大家發佈。 – rebelliard 2011-04-13 13:23:32

+0

@druttka我只是忘了它。謝謝:) – archil 2011-04-13 13:25:21

2

接受的答案是非常有幫助的。我爲我的項目進行了一些更新和更新,我覺得這個版本對於那些只想跳槽並完成任務的人來說會更加清晰。

變化包括:

  • 升級爲使用匿名類型而不是IDictionary的,因爲這似乎是現在的標準。
  • 刪除了Begin/End ...語法,因爲我只會在using()語法中使用它,爲此我覺得這更清晰。
  • 爲了清晰起見,調整了命名。
  • 新增了一個headerText參數,我的面板使用它創建一個單獨的div標題。如果你不需要/需要,這很容易刪除。
  • 重構了幾種方法。
  • 如果您碰巧正在尋找KendoUI的面板幫手 - 好吧,這恰好是這樣的。我有一個名爲Panel的類,它引用了這個類,並且只是爲KendoUI標籤添加了邊距和寬度。

    using System; using System.Diagnostics.CodeAnalysis;使用System.IO的 ;使用System.Web的 。MVC;

    命名空間MyProject.Web.HtmlHelpers.Extensions { 公共靜態類LayoutExtensions { 公共靜態StyledPanel面板(在此的HtmlHelper的HtmlHelper,對象htmlAttributes = NULL,串HEADERTEXT = NULL){ 返回 GetStyledPanel(的HtmlHelper,HEADERTEXT ,htmlAttributes); }

    private static StyledPanel GetStyledPanel(this HtmlHelper htmlHelper, string headerText, object htmlAttributes) 
        { 
    
         if (!string.IsNullOrWhiteSpace(headerText)) 
          RenderHeading(htmlHelper, headerText); 
    
         RenderDiv(htmlHelper, htmlAttributes); 
    
         return new StyledPanel(htmlHelper.ViewContext.Writer); 
        } 
    
        private static void RenderHeading(HtmlHelper htmlHelper, string headerText) 
        { 
         TagBuilder tagBuilder = new TagBuilder("div"); 
         tagBuilder.Attributes.Add("class", "panelHead"); 
         tagBuilder.SetInnerText(headerText); 
    
         htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.Normal)); 
        } 
    
        private static void RenderDiv(HtmlHelper htmlHelper, object htmlAttributes) 
        { 
         TagBuilder Tag = new TagBuilder("div"); 
         Tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); 
         Tag.MergeAttribute("class", "panel k-block k-shadow"); 
    
         htmlHelper.ViewContext.Writer.Write(Tag.ToString(TagRenderMode.StartTag));   
        } 
    
    } 
    
    public class StyledPanel : IDisposable 
    { 
        private bool m_Disposed; 
        private readonly TextWriter m_Writer; 
    
        public StyledPanel(TextWriter writer) 
        { 
         if (writer == null) 
          throw new ArgumentNullException("Writer was null. This should never happen."); 
    
         m_Writer = writer; 
        } 
    
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] 
        public void Dispose() 
        { 
         Dispose(true); 
         GC.SuppressFinalize(this); 
        } 
    
        protected virtual void Dispose(bool disposing) 
        { 
         if (!m_Disposed) 
         { 
          m_Disposed = true; 
          m_Writer.Write("</div>"); 
         } 
        } 
    
        public void EndForm() 
        { 
         Dispose(true); 
        } 
    } 
    

    }

用法可能是這樣的:

@using (Html.Panel(headerText: "My Header", 
        htmlAttributes: new { style = "width: 800px;" })) 
{ 
    <table> 
      <tr> 
       <td class="label">First Name:</td> 
       <td class="content"><input name="thing" class="k-textbox" /></td> 

       <td class="label">Last Name:</td> 
       <td class="content"><input name="thing" class="k-textbox" /></td> 
      </tr> 
    </table> 
} 

或者只是:

@using (Html.Panel()) 
{ 
    <table> 
      <tr> 
       <td class="label">First Name:</td> 
       <td class="content"><input name="thing" class="k-textbox" /></td> 

       <td class="label">Last Name:</td> 
       <td class="content"><input name="thing" class="k-textbox" /></td> 
      </tr> 
    </table> 
}