【问题标题】:Adding html spans into a LabelFor - MVC 3将 html 跨度添加到 LabelFor - MVC 3
【发布时间】:2011-10-27 22:37:36
【问题描述】:

我有一个复杂的表单,需要 javascript 和非 javascript 用户使用。我的应用程序是 .NET MVC 3。

表格有很多字段,如果他们以特定方式回答上一个问题,则必须填写这些字段。启用 javascript 后,我​​可以根据用户交互显示或隐藏相关问题。如果没有 javascript,我想为问题标签本身添加更多细节,因为默认情况下会显示所有问题(就像填写表格的纸质版本一样)。

理想情况下,我希望标签类似于:

<label><span class="non-js">If you were a smoker, when</span><span class="js">When</span> did you stop smoking?</label>

这样我可以关闭 CSS 中的相关文本(我希望屏幕阅读器可以处理这个问题)。

所以javascript用户得到:

When did you stop smoking?

非javascript用户得到:

If you were a smoker, when did you stop smoking?

我的问题是我该怎么做,因为 LabelFor 助手不允许在字符串中使用 html。

更新

抱歉,我忘记了一个重要信息,因为我的标签当前由模型中的 [Display(Name = "When did you stop smoking?")] 注释填充。 Idelly 我想把它放在这里并有类似的东西:

[Display(JS = "When", NonJS = "If you were a smoker, when", Both="did you stop smoking?")]

这可能吗?

更新 2

好的,这就是我到目前为止所得到的。这是我的属性:

public class MultipleDisplayNameAttribute : Attribute, IMetadataAware
{
    public string CustomerDisplayName { get; set; }
    public string CustomerJSAlternative { get; set; }
    public string CustomerNonJSAlternative { get; set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        string jsPart;
        string nonJsPart;
        jsPart = (CustomerJSAlternative != null) ? String.Format("<span class='spnJs'>{0}</span>", CustomerJSAlternative) : "";
        nonJsPart = (CustomerNonJSAlternative != null) ? String.Format("<span class='spnNonJs'>{0}</span>", CustomerNonJSAlternative) : "";
        metadata.DisplayName = String.Format("{0}{1}{2}", jsPart, nonJsPart, CustomerDisplayName);
    }
}

不幸的是,我现在卡住了,因为它在屏幕上显示为未编码。即它实际上是这样在屏幕上出现的:

<span class="non-js">If you were a smoker, when</span><span class="js">When</span> did you stop smoking?

有什么方法可以改变 displayName 元数据属性来解决这个问题吗?

更新 3 和解决方案

在答案和http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx 的帮助下,我设法得到了我想要的解决方案:

我的属性:

public class MultipleDisplayNameAttribute : Attribute, IMetadataAware
{
    public string CustomerDisplayName { get; set; }
    public string CustomerJSAlternative { get; set; }
    public string CustomerNonJSAlternative { get; set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["JS"] = (CustomerJSAlternative != null) ? String.Format("<span class='spnJs'>{0}</span>", CustomerJSAlternative) : "";
        metadata.AdditionalValues["NoJS"] = (CustomerNonJSAlternative != null) ? String.Format("<span class='spnNonJs'>{0}</span>", CustomerNonJSAlternative) : "";
        metadata.DisplayName = CustomerDisplayName;
    }
}

我的助手:

    public static MvcHtmlString JsAndNonJsCheckFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
        HtmlString jsLabel = new HtmlString("");
        HtmlString noJsLabel = new HtmlString("");
        string htmlFieldName = ExpressionHelper.GetExpressionText(expression);

        string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
        if (String.IsNullOrEmpty(labelText))
            return MvcHtmlString.Empty;


        if(metadata.AdditionalValues.ContainsKey("JS"))
            jsLabel = new HtmlString((string)metadata.AdditionalValues["JS"]);


        if (metadata.AdditionalValues.ContainsKey("NoJS"))
            noJsLabel = new HtmlString((string)metadata.AdditionalValues["NoJS"]);

        TagBuilder tagBuilder = new TagBuilder("label");
        tagBuilder.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
        tagBuilder.InnerHtml = String.Format("{0}{1}{2}", jsLabel, noJsLabel, labelText);

        return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
    }

工作完成(最终!)感谢大家的帮助!

【问题讨论】:

  • 嘿@Sniffer,你看我的回答了吗?你还需要什么额外的东西吗?
  • 嗨@Millimetric 不幸的是我错过了问题的关键部分。你能看到上面的“更新”部分吗?对此感到抱歉。
  • 是可能的,你所缺少的只是编写一个自定义Attribute,并在你的LabelFor函数中获取数据。 (理想情况下,将其填充到 ModelMetaData,尽管反射是一种选择。)

标签: asp.net-mvc-3


【解决方案1】:

您当前的问题是LabelFor 的工作原理。这是LabelFor 的反编译源代码(来自 MVC2。实际源代码可能更好,并且可以免费下载):

    public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
      return LabelExtensions.LabelHelper((HtmlHelper) html, ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, html.ViewData), ExpressionHelper.GetExpressionText((LambdaExpression) expression));
    }

    internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName)
    {
      string str = metadata.DisplayName;
      if (str == null)
      {
        string propertyName = metadata.PropertyName;
        if (propertyName == null)
          str = Enumerable.Last<string>((IEnumerable<string>) htmlFieldName.Split(new char[1]
          {
            '.'
          }));
        else
          str = propertyName;
      }
      string innerText = str;
      if (string.IsNullOrEmpty(innerText))
        return MvcHtmlString.Empty;
      TagBuilder tagBuilder = new TagBuilder("label");
      tagBuilder.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
      tagBuilder.SetInnerText(innerText);
      return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
    }
  }

你基本上可以复制这段代码,更改方法名称,并将代码的倒数第二行更改为:

tagBuilder.InnerHtml(innerText);

您将拥有一个不会转义 HTML 的有效解决方案。

【讨论】:

  • 谢谢 - 这让我走上了正轨。请注意 - 它是 InnerHtml,而不是 SetInnerHtml。干杯!
【解决方案2】:

您可以为 Html 编写自己的 LabelFor 扩展。我建议这样做,因为您可以将 js 和非 js 文本作为参数传递,而不必一遍又一遍地编写 HTML。这是基本的标签类型帮助器:

using System;
namespace MvcApplication1.Helpers
{
      public class LabelHelper
      {
           public static string LabelJsNonJs(this HtmlHelper helper, string target, string nonJs, string js, string commonText)
           {
                return String.Format("<label for='{0}'><span class='non-js'>{1}</span><span class='js'>{2}</span>{3}</label>", target, nonJs, js, commonText);
           }
      }
}

您可以通过为 MvcApplication1.Helpers 命名空间添加 using 在视图中使用它。

请参阅http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx 了解有关制作 LabelFor 类型助手的更多信息(稍微复杂一点,我没有太多时间)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 2021-08-02
    相关资源
    最近更新 更多