【发布时间】: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