Asp MVC 4创建自定义html helper方法,类似于html . beginform

本文关键字:html 方法 类似于 beginform helper Asp 创建 自定义 MVC | 更新日期: 2023-09-27 17:51:10

我有以下html:

<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>
}

我开始创建我的helper方法

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>");
            }
        }
    }
}

和我已经注册了命名空间~/Views/web.config

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

Asp MVC 4创建自定义html helper方法,类似于html . beginform

不能返回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));

Slawek有正确的答案,但我想我应该用我的经验来补充一下。

我想创建一个帮助器来在页面上显示小部件(就像jQuery的小部件带有标题栏和内容部分)。大意是:

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

MVC源代码使用了与Slawek发布的类似的东西,但是我觉得在helper中放置开始标记而在实际对象中放置结束标记并不"整洁",也没有将关注点放在正确的位置。如果我想改变外观,我现在在两个地方这样做,而不是我认为是一个合乎逻辑的地方。所以我想到了下面这个:

/// <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);
}

然后我们可以像我在这篇文章的开头那样使用它

asp.net mvc的BeginForm方法返回MvcForm类的IDisposable实例。如果你在codeplex上查看asp.net mvc代码,你可以查看asp.net mvc团队是如何开发这个特性的。

看看这些链接:

MvcForm class (iddisposable)http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/8b17c2c49f88 src/System.Web.Mvc/Html/MvcForm.cs

Forms Extensions (for html helper)http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/8b17c2c49f88 src/System.Web.Mvc/Html/FormExtensions.cs