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)); } }