1

我需要为 Mvc 推出我自己的 BeginLabel 助手。我从 html.beginForm / ajax.beginForm 方法的 Mvc 源代码中检查/窃取了这个概念。

public static Label BeginLabel(this HtmlHelper htmlHelper)
{
    TagBuilder tagBuilder = new TagBuilder("label");
    HttpResponseBase response = htmlHelper.ViewContext.HttpContext.Response;
    response.Write(tagBuilder.ToString(TagRenderMode.StartTag));
    return new Label(response);
}

Label仅实现 IDisposable 接口以启用关闭标签:

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        _disposed = true;
        _httpResponse.Write("</label>");
    }
}

用法如下所示:

@using (Html.BeginLabel())
{
    @Html.TextBoxFor(f => f.FirstName)
    @Html.ValidationMessageFor(f => f.FirstName)
}

看起来我错过了一些东西,因为标签总是在 html 的顶部呈现,虽然这对我来说很明显,因为我正在写响应,但我看不到本机 BeginForm() 是如何实现这一点的. 任何人都可以对此有所了解吗?

4

1 回答 1

3
public class MvcLabel : IDisposable
{
    // Fields
    private bool _disposed;
    private readonly TextWriter _writer;

    public MvcLabel(ViewContext viewContext)
    {
        if (viewContext == null)
        {
            throw new ArgumentNullException("viewContext");
        }
        this._writer = viewContext.Writer;
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (!this._disposed)
        {
            this._disposed = true;
            this._writer.Write("</label>");
        }
    }

    public void EndLabel()
    {
        this.Dispose(true);
    }
}

public static class HtmlHelperExtension
{
    // Methods
    public static MvcLabel BeginLabel(this HtmlHelper html, string expression)
    {
        return html.BeginLabel(expression, null);
    }

    public static MvcLabel BeginLabel(this HtmlHelper html, string expression, string labelText)
    {
        return LabelHelper(html, ModelMetadata.FromStringExpression(expression, html.ViewData), expression, labelText);
    }

    public static MvcLabel BeginLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        return html.BeginLabelFor<TModel, TValue>(expression, null);
    }

    public static MvcLabel BeginLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string labelText)
    {
        return LabelHelper(html, ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, html.ViewData), ExpressionHelper.GetExpressionText(expression), labelText);
    }

    public static MvcLabel BeginLabelForModel(this HtmlHelper html)
    {
        return html.BeginLabelForModel(null);
    }

    public static MvcLabel BeginLabelForModel(this HtmlHelper html, string labelText)
    {
        return LabelHelper(html, html.ViewData.ModelMetadata, string.Empty, labelText);
    }

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

    internal static MvcLabel LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, string labelText = null)
    {
        string str = labelText ?? (metadata.DisplayName ?? (metadata.PropertyName ?? htmlFieldName.Split(new char[] { '.' }).Last<string>()));

        TagBuilder tagBuilder = new TagBuilder("label");
        tagBuilder.Attributes.Add("for", TagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));

        html.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));

        if (!string.IsNullOrEmpty(str))
        {
            tagBuilder = new TagBuilder("span");
            tagBuilder.SetInnerText(str);
            html.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.Normal));
        }

        return new MvcLabel(html.ViewContext);
    }
}

希望我能帮助别人...

于 2011-10-22T20:58:09.857 回答