実は ModelMetadata には Watermark プロパティが用意されていて、Display 属性の Prompt プロパティの値が自動的にセットされるようになっています。
つまり、この値を使ってあげれば属性ベースで Watermark を実装できそうです。というわけで、jQuery Watermark プラグインを使って実装してみたので、早速ソースコードを出します。
ちなみに jQuery Watermark プラグインは jquery-watermark - jQuery plugin adds watermark capability to HTML input elements - Google Project Hosting を使いました。
まずはモデルクラスです。
public class Product { public int ProductId { get; set; } [Required] [DataType(DataType.Text)] [Display(Prompt = "名前")] public string Name { get; set; } [Required] [DataType(DataType.MultilineText)] [Display(Prompt = "サマリー")] public string Summary { get; set; } [Required] [DataType(DataType.Currency)] [Display(Prompt = "価格")] public decimal Price { get; set; } }
Display 属性で Prompt プロパティに Watermark で表示したい文字列を指定しています。次は HTML ヘルパーです。
public static IHtmlString Watermark<TModel>(this HtmlHelper<TModel> htmlHelper) { var metadata = htmlHelper.ViewData.ModelMetadata; var watermarks = new StringBuilder(); foreach (var property in metadata.Properties.Where(p => !string.IsNullOrEmpty(p.Watermark))) { watermarks.AppendFormat(@"$(""*[name='{0}']"").watermark(""{1}"");", property.PropertyName, property.Watermark); } var tagBuilder = new TagBuilder("script"); tagBuilder.MergeAttribute("type", "text/javascript"); tagBuilder.InnerHtml = "$(function() { " + watermarks + " });"; return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal)); }
内容としてはモデル全体の ModelMetadata を取得して Properties コレクションを調べ、Watermark が指定されている場合には jQuery Watermark のメソッドを呼び出すコードを生成しているだけです。ちなみに出力されたコードは以下のような感じです。
<script type="text/javascript"> $(function() { $("*[name='Name']").watermark("名前"); $("*[name='Summary']").watermark("サマリー"); $("*[name='Price']").watermark("価格"); }); </script>
読みやすいように改行とインデントを追加しました。name 属性の値で判別するようにしましたが、id を使っても問題ないかもしれません。
最後はビューで jquery.watermark.js の追加と Watermark メソッドを呼び出すだけです。場所は別にどこでもいいです。
@Html.Watermark()
これで全ての準備が出来たので、実際に実行して確認してみます。
Prompt で指定した文字列が出力されていますね。
ちなみに ModelMetadata は AdditionalValues プロパティと AdditionalMetadata 属性が用意されているので、かなり自由に拡張出来るようになっています。