在MVC的view页面上,我们虽然可以通过给html attribute手写new { @placeholder = "something" }来增加placeholder属性,但这样做对于MVC3框架而言不是非常地道。一个比较好的办法是通过拓展MVC,来增加一个DataAnnotation属性,最终在Model中指定PlaceHolder。下面的方法是我在stackoverflow网站上撸到的,稍作修改并测试后发现非常牛逼,分享给大家。
首先,我们要码一个PlaceHolderAttribute类,让它继承Attribute, IMetadataAware两个接口。注意类名是包含Attribute后缀的,但最终使用的时候是只取PlaceHolder这个名字的。(这个机制是.NET自己撸的,我们不用管)
public class PlaceHolderAttribute : Attribute, IMetadataAware { private readonly string _placeholder; public PlaceHolderAttribute(string placeholder) { _placeholder = placeholder; } public void OnMetadataCreated(ModelMetadata metadata) { metadata.AdditionalValues["placeholder"] = _placeholder; } }
这个类你可以丢在类库里或MVC网站项目文件夹里,最后要注意一下引用和命名空间。我的习惯是把这些Attribute类都放在网站下的Infrastructures文件夹中。
但现在还不够,我们必须自定义一个PlaceHolder的显示模板。建一个string类型的显示模板,放到“~/Views/Shared/EditorTemplates/string.cshtml”里:
@{ var placeholder = string.Empty; if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("placeholder")) { placeholder = ViewData.ModelMetadata.AdditionalValues["placeholder"] as string; } } @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { placeholder = placeholder })
这个模板可以根据你的需求充分自定义。
接下来,我们就可以在Model中用这个placeholder特征了:
Model:
public class MyModel { [PlaceHolder("Enter title here")] public string Title { get; set; } }
Controller:
public ActionResult Index() { var model = new MyModel(); return View(model); }
View:
@model MVCPlaceHolderDemo.Models.MyModel <p> @Html.EditorFor(x => x.Title) </p>
最后效果如下:
为了兼容不同浏览器,我们还需要先检查一下浏览器是否支持PlaceHolder属性,如果不行就用JQuery加上。配合MVC3默认模板里自带的Modernizr,可以在layout页面加上这段脚本:
$(document).ready(function () { if (!Modernizr.input.placeholder) { $("input").each( function () { if ($(this).val() == "" && $(this).attr("placeholder") != "") { $(this).val($(this).attr("placeholder")); $(this).focus(function () { if ($(this).val() == $(this).attr("placeholder")) $(this).val(""); }); $(this).blur(function () { if ($(this).val() == "") $(this).val($(this).attr("placeholder")); }); } }); } });
这样就可以兼容了~