Html5的占位符与.NET MVC 3razorEditorFor扩展?
有没有办法编写Html5占位符使用@ Html.EditorFor,或者我应该只使用TextBoxFor扩展
@Html.TextBoxFor(model => model.Title, new { @placeholder = "Enter title here"})
或者是否有必要编写我们自己的自定义扩展,通过DataAnnotations(类似于这个 )可以使用'Description'显示属性?
当然,同样的问题也适用于“自动对焦”。
你可以看看下面的文章来编写一个自定义的DataAnnotationsModelMetadataProvider
。
还有另外一个,更多的ASP.NET MVC 3ish方法来继续使用新引入的IMetadataAware接口。
首先创build一个实现这个接口的自定义属性:
public class PlaceHolderAttribute : Attribute, IMetadataAware { private readonly string _placeholder; public PlaceHolderAttribute(string placeholder) { _placeholder = placeholder; } public void OnMetadataCreated(ModelMetadata metadata) { metadata.AdditionalValues["placeholder"] = _placeholder; } }
然后用它来装饰你的模型:
public class MyViewModel { [PlaceHolder("Enter title here")] public string Title { get; set; } }
接下来定义一个控制器
public class HomeController : Controller { public ActionResult Index() { return View(new MyViewModel()); } }
相应的观点:
@model MyViewModel @using (Html.BeginForm()) { @Html.EditorFor(x => x.Title) <input type="submit" value="OK" /> }
最后是编辑器模板( ~/Views/Shared/EditorTemplates/string.cshtml
):
@{ var placeholder = string.Empty; if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("placeholder")) { placeholder = ViewData.ModelMetadata.AdditionalValues["placeholder"] as string; } } <span> @Html.Label(ViewData.ModelMetadata.PropertyName) @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { placeholder = placeholder }) </span>
作为达林·季米特洛夫的回答中的smnbss评论, Prompt
存在就是为了这个目的,所以不需要创build一个自定义的属性 。 从文档:
获取或设置用于在UI中为提示设置水印的值。
要使用它,只需修饰您的视图模型的属性,如下所示:
[Display(Prompt = "numbers only")] public int Age { get; set; }
这个文本然后放在ModelMetadata.Watermark
。 开箱即用,MVC 3中的默认模板忽略了Watermark
属性,但是使其工作起来非常简单。 所有你需要做的就是调整默认的string模板,告诉MVC如何渲染它。 只要像Darin那样编辑String.cshtml,不同于从ModelMetadata.AdditionalValues
获取水印,您可以直接从ModelMetadata.Watermark
:
〜/查看/共享/ EditorTemplates / String.cshtml:
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", placeholder = ViewData.ModelMetadata.Watermark })
就是这样。
正如你所看到的,使所有的工作的关键是placeholder = ViewData.ModelMetadata.Watermark
位。
如果您还想为多行文本框(textareas)启用水印,则可以对MultilineText.cshtml执行相同的操作:
〜/查看/共享/ EditorTemplates / MultilineText.cshtml:
@Html.TextArea("", ViewData.TemplateInfo.FormattedModelValue.ToString(), 0, 0, new { @class = "text-box multi-line", placeholder = ViewData.ModelMetadata.Watermark })
我实际上更喜欢大部分时间使用占位符文本的显示名称。 这是一个使用DisplayName的例子:
@Html.TextBoxFor(x => x.FirstName, true, null, new { @class = "form-control", placeholder = Html.DisplayNameFor(x => x.FirstName) })
我写了这样一个简单的类:
public static class WatermarkExtension { public static MvcHtmlString WatermarkFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) { var watermark = ModelMetadata.FromLambdaExpression(expression, html.ViewData).Watermark; var htmlEncoded = HttpUtility.HtmlEncode(watermark); return new MvcHtmlString(htmlEncoded); } }
用法如下:
@Html.TextBoxFor(model => model.AddressSuffix, new {placeholder = Html.WatermarkFor(model => model.AddressSuffix)})
和视图模型中的属性:
[Display(ResourceType = typeof (Resources), Name = "AddressSuffixLabel", Prompt = "AddressSuffixPlaceholder")] public string AddressSuffix { get { return _album.AddressSuffix; } set { _album.AddressSuffix = value; } }
通知提示参数。 在这种情况下,我使用资源中的string进行本地化,但只能使用string,只是避免使用ResourceType参数。
我使用这种方式与资源文件(不需要提示了!)
@Html.TextBoxFor(m => m.Name, new { @class = "form-control", placeholder = @Html.DisplayName(@Resource.PleaseTypeName), autofocus = "autofocus", required = "required" })
这里是我使用上面的想法可以用于TextBoxFor和PasswordFor的解决scheme:
public static class HtmlHelperEx { public static MvcHtmlString TextBoxWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) { var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); return htmlHelper.TextBoxFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark)); } public static MvcHtmlString PasswordWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) { var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); return htmlHelper.PasswordFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark)); } } public static class HtmlAttributesHelper { public static IDictionary<string, object> AddAttribute(this object htmlAttributes, string name, object value) { var dictionary = htmlAttributes == null ? new Dictionary<string, object>() : htmlAttributes.ToDictionary(); if (!String.IsNullOrWhiteSpace(name) && value != null && !String.IsNullOrWhiteSpace(value.ToString())) dictionary.Add(name, value); return dictionary; } public static IDictionary<string, object> ToDictionary(this object obj) { return TypeDescriptor.GetProperties(obj) .Cast<PropertyDescriptor>() .ToDictionary(property => property.Name, property => property.GetValue(obj)); } }