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

Asp MVC 4 создает пользовательский метод html helper, аналогичный Html.BeginForm

У меня есть следующий html:

<div data-bind="stopBindings">

    <div data-viewId="languageList" data-bind="with: viewModel">
       <table>
              <tr>
                   <td ></td>
              </tr>
       <table>
    </div>

</div>

I want to make a custom html helper and use it like this (similar to Html.BeginForm)

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

I started making my helper method

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

    }

I read how to make basic html helper but the examples I saw does not give me information how to make it in my case. I am very new to asp mvc and every help will be greatly appreciated.

UPDATE 2:

Obviously I am missing something. I am calling this in my view:

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

Everything seems fine it even has intellisense. But the output in the browser is the following:

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


test

 } 

This is my helper method:

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

and I have registered the namespace in ~/Views/web.config

 
16
nl ja de

3 ответы

Вы не можете вернуть 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));
19
добавлено
см. обновление выше, касающееся вашего сообщения. Спасибо!
добавлено автор Mdb, источник
Я выполнил свою реализацию, следуя вашему коду, но результат не был таким же заостренным. Можете ли вы посмотреть мой пост, я обновил его снова.
добавлено автор Mdb, источник
Это сработало. Знаете ли вы, почему это не сработало? Разве оба способа равны?
добавлено автор Mdb, источник
Используйте , используя (Html.BeginView ()) вместо @ Html.BeginView()
добавлено автор Sławomir Rosiek, источник
Знак @ вызывает результат рендеринга бритвы метода. Если ваш метод возвращает строку или MvcHtmlString, то она записывается в Writer. Если ваш метод возвращает MyView, тогда бритва вызывает ToString в MyView.
добавлено автор Sławomir Rosiek, источник

Slawek has the correct answer, but I thought I would add to it with my experience.

Я хотел создать помощник для отображения виджетов на странице (почти как виджеты jQuery с заголовком и частью контента). Что-то вроде:

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

Источник MVC использует что-то похожее на то, что опубликовал Slawek, но мне кажется, что размещение начального тега в вспомогательном и конечном теге в фактическом объекте не было «аккуратным», и оно не вызывало беспокойства в месте corect. Должен ли я изменить внешний вид, теперь я делаю это в двух местах, вместо того, что я чувствовал, было одно логическое место. Поэтому я придумал следующее:

/// 
/// Widget container
/// 
/// 
/// 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.
/// 
public class HtmlWidget : IDisposable
{
    #region CTor

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

    /// 
    /// 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
    /// 
    /// Reference to the viewcontext
    /// Title of the widget
    /// Width of the widget (column layout)
    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

    /// 
    /// Outputs the opening HTML for the widget
    /// 
    /// Title of the widget
    /// Widget width (columns layout)
    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());
    }

    /// 
    /// Outputs the closing HTML for the widget
    /// 
    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
}

Затем это делает наш помощник немного понятнее (и нет кода интерфейса в двух местах):

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

Тогда мы можем использовать его, как я сделал в верхней части этого сообщения.

6
добавлено

Метод BeginForm asp.net mvc возвращает экземпляр IDisposable класса MvcForm . Если вы посмотрите в код asv.net mvc на codeplex , вы можете проверить, как развилась команда asp.net mvc эта особенность.

Взгляните на тезисы ссылок:

MvcForm class (IDisposable) 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

2
добавлено
DotNetRuChat
DotNetRuChat
2 992 участник(ов)

Чат русскоязычного .NET сообщества http://dotnet.ru/ Вам могут быть интересны: @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @xamarin_russia, @microsoftstackjobs, @uwp_ru Флуд в @dotnettalks

Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

pro.net
pro.net
710 участник(ов)

Обсуждение .NET Framework и всего, что с ним связано. Правила: не флудить не по теме, уважать ваших коллег и никакой рекламы (объявления о вакансиях можно согласовать с @AlexFails). Флудилка: @dotnettalks Участник @proDOT

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot

.NET Talks: Force Push Masters
.NET Talks: Force Push Masters
490 участник(ов)

Свободный чат .NET разработчиков. Правила: t.me/dotnettalks/56823 Вам могут быть интересны: @dotnetruchat, @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @dotnetgroup, @xamarin_russia, @microsoftstackjobs, @uwp_ru http://combot.org/chat/-1001128250813

.NET Chat Убежище
.NET Chat Убежище
246 участник(ов)

Чат .NET разработчиков под эгидой MSK/SPB .NET Community Group Вам могут быть интересны: @fsharp_chat, @dotnetruchat, @cilchat, @xamarin_russia, @microsoftstackjobs, @dotnetgroup Флуд в @dotnettalks

.NET CIL Chat
.NET CIL Chat
54 участник(ов)

.NET CIL (aka IL aka MSIL)