2013-01-09 32 views
16

我有以下的html:天冬氨酸MVC 4創建類似的自定義HTML輔助方法Html.BeginForm

<div data-bind="stopBindings"> 

    <div data-viewId="languageList" data-bind="with: viewModel"> 
     <table> 
       <tr> 
        <td ><label for="availableLanguages">Available Languages:</label></td> 
       </tr> 
     <table> 
    </div> 

</div> 

我想打一個自定義的HTML幫助,並使用它像這樣(類似於Html.BeginForm

@Html.BeginView() 
{ 
    <table> 
     <tr> 
      <td ><label for="availableLanguages">Available Languages:</label></td> 
     </tr> 
    </table> 
} 

我開始做我的助手方法

public static class BeginViewHelper 
    { 
     public static MvcHtmlString BeginView(this HtmlHelper helper, string viewId) 
     { 

      var parentDiv = new TagBuilder("div"); 
      parentDiv.MergeAttribute("data-bind", "preventBinding: true"); 
      return new MvcHtmlString(); 
     } 

    } 

我讀了如何使基本的HTML幫手,但我看到的例子並沒有給我信息如何在我的情況下。我對asp mvc很陌生,每一個幫助將不勝感激。

更新2:

顯然我失去了一些東西。我打電話給我看:

@Html.BeginView() 
{ 
    <table> 
     <tr> 
      <td ><label >test</label></td> 
     </tr> 
    </table> 
} 

一切似乎都很好,它甚至具有智能感知。但在瀏覽器中輸出如下:

Omega.UI.WebMvc.Helpers.BeginViewHelper+MyView { 


test 

} 

這是幫助我的方法:

namespace Omega.UI.WebMvc.Helpers 
{ 
    public static class BeginViewHelper 
    { 
     public static IDisposable BeginView(this HtmlHelper helper) 
     { 
      helper.ViewContext.Writer.Write("<div data-bind=\"preventBinding: true\">"); 
      helper.ViewContext.Writer.Write("<div data-viewId=\"test\">"); 

      return new MyView(helper); 
     } 

     class MyView : IDisposable 
     { 
      private HtmlHelper _helper; 

      public MyView(HtmlHelper helper) 
      { 
       this._helper = helper; 
      } 

      public void Dispose() 
      { 
       this._helper.ViewContext.Writer.Write("</div>"); 
       this._helper.ViewContext.Writer.Write("</div>"); 
      } 
     } 
    } 
} 

,我已經註冊了命名空間在〜/查看/ web.config中

<add namespace="Omega.UI.WebMvc.Helpers" /> 

回答

18

您不能返回MvcHtmlString。相反,您應該將html寫入作者並返回實現IDisposable的類,並且在調用Dispose時將寫入HTML的關閉部分。

public static class BeginViewHelper 
{ 
    public static IDisposable BeginView(this HtmlHelper helper, string viewId) 
    { 
     helper.ViewContext.Writer.Write(string.Format("<div id='{0}'>", viewId)); 

     return new MyView(helper); 
    } 

    class MyView : IDisposable 
    { 
     private HtmlHelper helper; 

     public MyView(HtmlHelper helper) 
     { 
      this.helper = helper; 
     } 

     public void Dispose() 
     { 
      this.helper.ViewContext.Writer.Write("</div>"); 
     } 
    } 
} 

如果你有更復雜的結構,你可以嘗試使用TagBuilder:

TagBuilder tb = new TagBuilder("div"); 
helper.ViewContext.Writer.Write(tb.ToString(TagRenderMode.StartTag)); 
+0

請參閱上面有關您的帖子的更新。謝謝! – Mdb

+0

我按照你的代碼做了我的實現,但結果並不如人意。你能看到我的帖子,我已經更新了一遍。 – Mdb

+3

使用'使用(Html.BeginView())'而不是'@ Html.BeginView()' –

2

asp.net mvc的BeginForm方法返回MvcForm類的IDisposable實例。如果您查看asp.net mvc code on codeplex,可以查看asp.net mvc團隊如何開發此功能。

在論文的鏈接看看:

MvcForm類(IDisposable接口) http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/8b17c2c49f88#src/System.Web.Mvc/Html/MvcForm.cs

形式擴展庫(HTML輔助) http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/8b17c2c49f88#src/System.Web.Mvc/Html/FormExtensions.cs

6

Slawekcorrect answer,但我想我會添加到它與我的經驗。

我想創建一個幫助器來在頁面上顯示小部件(幾乎像jQuery的小部件,標題欄和內容部分)。東西的效果:

@using (Html.BeginWidget("Widget Title", 3 /* columnWidth */)) 
{ 
    @* Widget Contents *@ 
} 

的MVC源使用類似於Slawek貼的東西,但我覺得在實際的對象將開始標記的助手和結束標記不是「整潔」,也不它是否在覈心地方擔憂?如果我想改變外觀,我現在在兩個地方這樣做,而不是我認爲是一個合乎邏輯的地方。所以,我想出了以下內容:

/// <summary> 
/// Widget container 
/// </summary> 
/// <remarks> 
/// We make it IDIsposable so we can use it like Html.BeginForm and when the @using(){} block has ended, 
/// the end of the widget's content is output. 
/// </remarks> 
public class HtmlWidget : IDisposable 
{ 
    #region CTor 

    // store some references for ease of use 
    private readonly ViewContext viewContext; 
    private readonly System.IO.TextWriter textWriter; 

    /// <summary> 
    /// Initialize the box by passing it the view context (so we can 
    /// reference the stream writer) Then call the BeginWidget method 
    /// to begin the output of the widget 
    /// </summary> 
    /// <param name="viewContext">Reference to the viewcontext</param> 
    /// <param name="title">Title of the widget</param> 
    /// <param name="columnWidth">Width of the widget (column layout)</param> 
    public HtmlWidget(ViewContext viewContext, String title, Int32 columnWidth = 6) 
    { 
     if (viewContext == null) 
      throw new ArgumentNullException("viewContext"); 
     if (String.IsNullOrWhiteSpace(title)) 
      throw new ArgumentNullException("title"); 
     if (columnWidth < 1 || columnWidth > 12) 
      throw new ArgumentOutOfRangeException("columnWidth", "Value must be from 1-12"); 

     this.viewContext = viewContext; 
     this.textWriter = this.viewContext.Writer; 

     this.BeginWidget(title, columnWidth); 
    } 

    #endregion 

    #region Widget rendering 

    /// <summary> 
    /// Outputs the opening HTML for the widget 
    /// </summary> 
    /// <param name="title">Title of the widget</param> 
    /// <param name="columnWidth">Widget width (columns layout)</param> 
    protected virtual void BeginWidget(String title, Int32 columnWidth) 
    { 
     title = HttpUtility.HtmlDecode(title); 

     var html = new System.Text.StringBuilder(); 

     html.AppendFormat("<div class=\"box grid_{0}\">", columnWidth).AppendLine(); 
     html.AppendFormat("<div class=\"box-head\">{0}</div>", title).AppendLine(); 
     html.Append("<div class=\"box-content\">").AppendLine(); 

     this.textWriter.WriteLine(html.ToString()); 
    } 

    /// <summary> 
    /// Outputs the closing HTML for the widget 
    /// </summary> 
    protected virtual void EndWidget() 
    { 
     this.textWriter.WriteLine("</div></div>"); 
    } 

    #endregion 

    #region IDisposable 

    private Boolean isDisposed; 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    public virtual void Dispose(Boolean disposing) 
    { 
     if (!this.isDisposed) 
     { 
      this.isDisposed = true; 
      this.EndWidget(); 
      this.textWriter.Flush(); 
     } 
    } 

    #endregion 
} 

然後,才使得我們的幫助更加清楚一點(和在兩個地方沒有UI代碼):

public static HtmlWidget BeginWidget(this HtmlHelper htmlHelper, String title, Int32 columnWidth = 12) 
{ 
    return new HtmlWidget(htmlHelper.ViewContext, title, columnWidth); 
} 

然後我們可以使用它作爲我已經完成了這篇文章的頂部。