17

私は次の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>
}

ヘルパーメソッドを作り始めました

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" />
4

3 に答える 3

20

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));
于 2013-01-09T13:26:10.740 に答える
8

Slawek正しい答えを持っていますが、私は自分の経験でそれに追加すると思いました。

ページにウィジェットを表示するためのヘルパーを作成したいと考えていました (タイトル バーとコンテンツ部分を持つ jQuery のウィジェットとほとんど同じです)。効果のあるもの:

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

MVC ソースは Slawek が投稿したものに似たものを使用していますが、ヘルパーに開始タグを配置し、実際のオブジェクトに終了タグを配置するのは「きちんと」しておらず、適切な場所に懸念を保持していないように感じます。外観を変更したい場合は、論理的な 1 か所ではなく、2 か所で変更しています。だから私は次のことを思いついた:

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

次に、ヘルパーをもう少し明確にします (2 か所に UI コードはありません)。

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

その後、この記事の冒頭で行ったように使用できます。

于 2013-01-09T13:52:30.537 に答える
3

BeginFormasp.net mvcのメソッドは、クラスのIDisposableインスタンスを返します。codeplexのasp.netmvcコードMvcFormの内部を見ると、asp.netmvcチームがこの機能をどのように開発したかを確認できます。

これらのリンクを見てください:

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

于 2013-01-09T13:24:48.180 に答える