しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC で Watermark を属性を使って実装してみた

実は 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 属性が用意されているので、かなり自由に拡張出来るようになっています。