我有一个复杂的表单,需要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>
Run Code Online (Sandbox Code Playgroud)
这样我可以关闭CSS中的相关文本(我希望屏幕阅读器能够应对这一点).
所以javascript用户得到:
When did you stop smoking?
Run Code Online (Sandbox Code Playgroud)
和非JavaScript用户得到:
If you were a smoker, when did you stop smoking?
Run Code Online (Sandbox Code Playgroud)
我的问题是我将如何做到这一点,因为LabelFor助手不允许在字符串中使用html.
更新
对不起,我忘记了一个关键信息,因为我的标签目前正在填充[显示(姓名="你什么时候戒烟?")]模型中的注释.我想留意这里有类似的东西:
[Display(JS = "When", NonJS = "If you were a smoker, when", Both="did you stop smoking?")]
Run Code Online (Sandbox Code Playgroud)
这可能吗?
更新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);
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是我现在卡住了,因为它在屏幕上显示为未编码.即它实际上是在屏幕上出现的:
<span class="non-js">If you were a smoker, when</span><span class="js">When</span> did you stop smoking?
Run Code Online (Sandbox Code Playgroud)
有没有办法更改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;
}
}
Run Code Online (Sandbox Code Playgroud)
我的帮手:
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));
}
Run Code Online (Sandbox Code Playgroud)
完成工作(最终!)感谢大家的帮助!
您可以将自己的LabelFor扩展名编写为Html.我建议这样做,因为您可以将js和非js文本作为参数传递,而不必一遍又一遍地编写HTML.这是基本的Label类型助手:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过为MvcApplication1.Helpers命名空间添加using来在视图中使用它.
有关制作LabelFor类型助手的更多信息,请参阅http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx(稍微复杂一点)而且我没有太多时间).
你当前的问题是如何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);
}
}
Run Code Online (Sandbox Code Playgroud)
您基本上可以复制此代码,更改方法名称,并将第二行代码更改为:
tagBuilder.InnerHtml(innerText);
Run Code Online (Sandbox Code Playgroud)
而且你将拥有一个无法逃避HTML的工作解决方案.
| 归档时间: |
|
| 查看次数: |
8243 次 |
| 最近记录: |