【问题标题】:How to extend MVC3 Label and LabelFor HTML helpers?如何扩展 MVC3 标签和 LabelFor HTML 助手?
【发布时间】:2012-03-27 08:05:07
【问题描述】:

Html.LabelHtml.LabelFor 辅助方法不像大多数其他辅助方法那样支持 htmlAttributes 参数。但是,我想设置class。像这样的:

Html.LabelFor(model => model.Name, new { @class = "control-label" })

有没有一种简单的方法来扩展 Label/LabelFor 而不复制和扩展这些方法的 ILSpy disasm 输出?

【问题讨论】:

    标签: asp.net-mvc-3 extension-methods


    【解决方案1】:

    您可以通过创建自己的 LabelFor 轻松扩展标签:

    这样的事情应该可以满足您的需要

    public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
    {
      return LabelFor(html, expression, new RouteValueDictionary(htmlAttributes));
    }
    
    public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes)
    {
      ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
      string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
      string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
      if (String.IsNullOrEmpty(labelText))
      {
        return MvcHtmlString.Empty;
      }
    
      TagBuilder tag = new TagBuilder("label");
      tag.MergeAttributes(htmlAttributes);
      tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
      tag.SetInnerText(labelText);
      return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
    }
    

    更新 要使用刚刚在您的项目中创建的扩展方法,请将此行添加到您的 Views\web.config

    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
        <add namespace="MyProject.Helpers" />   <-- my extension
    
        ...
    
     </namespaces>
    </pages>
    

    【讨论】:

    • 我知道,但我试图避免复制反汇编/原始源输出。原始代码由 22 个方法组成,正确执行此操作我必须全部覆盖它们。
    • 没有。您只需创建扩展项目并在 web.config 中插入对项目的调用。
    【解决方案2】:
    public static class LabelExtensions
    {
        public static IHtmlString LabelFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            string labelText,
            object htmlAttributes
        )
        {
            var metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            var htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            return LabelHelper(htmlHelper, metadata, htmlFieldName, labelText, htmlAttributes);
        }
    
        public static IHtmlString Label(this HtmlHelper htmlHelper, string expression, string labelText, object htmlAttributes)
        {
            var metadata = ModelMetadata.FromStringExpression(expression, htmlHelper.ViewData);
            return LabelHelper(htmlHelper, metadata, expression, labelText, htmlAttributes);
        }
    
        private static IHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, string labelText, object htmlAttributes)
        {
            string str = labelText ?? (metadata.DisplayName ?? (metadata.PropertyName ?? htmlFieldName.Split(new char[] { '.' }).Last<string>()));
            if (string.IsNullOrEmpty(str))
            {
                return MvcHtmlString.Empty;
            }
            TagBuilder tagBuilder = new TagBuilder("label");
            tagBuilder.Attributes.Add("for", TagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));
            var attributes = new RouteValueDictionary(htmlAttributes);
            tagBuilder.MergeAttributes(attributes);
            tagBuilder.SetInnerText(str);
            return new HtmlString(tagBuilder.ToString(TagRenderMode.Normal));
        }
    }
    

    然后:

    @Html.LabelFor(x => x.SomeProperty, null, new { @class = "foo" })
    

    或:

    @Html.Label("SomeProperty", null, new { @class = "foo" })
    

    【讨论】:

    • 对不起,兄弟,如果我没有说清楚的话。我已经这样做了(复制 MVC 源并对其进行扩展),但是出于多种原因我想避免这种情况。我也喜欢保持干燥。我希望会有更优雅的东西。
    • 对不起,没有任何东西可以让你这样做。内置帮助器不可扩展,并且具有硬编码的属性。
    • 如何让编译器消除 myProject.Helpers.LabelExtensions.LabelFor 和 'System.Web.Mvc.Html.LabelExtensions.LabelFor 之间的歧义(页面上的其他内容需要)?
    • @Ungaro 你找到问题的答案了吗?
    • @nicola deep 不。我重写了我的扩展以引用 Lable 和 LableFor 并在我的整个视图中使用它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2014-11-24
    • 2016-03-19
    • 1970-01-01
    • 2019-04-09
    相关资源
    最近更新 更多