redwarrior’s diary

C#, ASP.NET, WEB, G*などの雑多な情報

ASP.NET MVC でテキストボックスとラベルに別の書式を使用する

ASP.NET MVCでは、ビューヘルパーを使用することで、テキストボックス等のフォーム部品をシンプルに記述することが出来ますよね。

さらに、***Forメソッドを使用すると、モデルクラスのプロパティを扱うことが出来て、EditorForメソッドやDisplayForメソッドではプロパティに指定した属性によってデフォルトの表示を変更することが出来ます。

例えば、以下のように日付や小数点の書式を指定したりします。(ASP.NET MVC5で確認しました。)

モデルクラス

[DisplayName("公開日")]
[DisplayFormat(DataFormatString = "{0:yyyy/MM/dd}", ApplyFormatInEditMode = true)]
public DateTime Published { get; set; }

[DisplayName("小数点を含む数値")]
[DisplayFormat(DataFormatString = "{0:0.000}", ApplyFormatInEditMode = true)]
public decimal Value { get; set; }

ビュー(編集画面)

@Html.EditorFor(model => model.Published)
@Html.EditorFor(model => model.Value)

ビュー(一覧画面)

@Html.DisplayFor(model => model.Published)
@Html.DisplayFor(model => model.Value)

この場合、ApplyFormatInEditModeが true に設定されているので、テキストボックスにも、ラベル(プロパティの値を文字列として出力することをここでは指します)にも同じ書式で表示されます。(公開日:2016/08/22、小数点を含む数値:1089.123)

課題

仕様変更で、テキストボックスとラベルで別の書式を使用することになりました。どうすれば良いでしょう?

ちなみに、以下のようにモデルに複数する方法はDisplayFormat属性が重複するのでダメでした。

[DisplayName("公開日")]
[DisplayFormat(DataFormatString = "{0:yyyy年MM月dd日}", ApplyFormatInEditMode = false)] //表示はyyyy年MM月dd日にしたい
[DisplayFormat(DataFormatString = "{0:yyyy/MM/dd}", ApplyFormatInEditMode = true)]
public DateTime Published { get; set; }

[DisplayName("小数点を含む数値")]
[DisplayFormat(DataFormatString = "{0:#,0.000}", ApplyFormatInEditMode = false)] //表示はカンマ区切りにしたい
[DisplayFormat(DataFormatString = "{0:0.000}", ApplyFormatInEditMode = true)]
public decimal Value { get; set; }

対処法

調べた結果、以下の方法で書式を分けることが出来ました。2か所変更します。

  1. モデルのDisplayFormat属性のApplyFormatInEditModeをfalseにする
  2. EditorForメソッドを使用せず、TextBoxForで書式を指定する。

変更後はこうなります。ビュー(一覧画面)に変更はありません。

モデルクラス

[DisplayName("公開日")]
[DisplayFormat(DataFormatString = "{0:yyyy年MM月dd日}", ApplyFormatInEditMode = false)]  //表示はyyyy年MM月dd日にしたい
public DateTime Published { get; set; }

[DisplayName("小数点を含む数値")]
[DisplayFormat(DataFormatString = "{0:#,0.000}", ApplyFormatInEditMode = false)] //表示はカンマ区切りにしたい
public decimal Value { get; set; }

ビュー(編集画面)

@Html.TextBoxFor(model => model.Published, "{0:yyyy/MM/dd}") //入力はyyyy/MM/dd
@Html.TextBoxFor(model => model.Value, "{0:0.000}") //入力はカンマ区切りなし

これでテキストボックスとラベルに別の書式を設定することが出来ました。

応用編

ビューを修正したくない場合は、独自テンプレートを用意することでビューの修正を無しにできます。

DateTime.cshtml

@model DateTime?

@Html.TextBoxFor(model => model, "{0:yyyy/MM/dd}") //入力はyyyy/MM/dd

decimal.cshtml

@model decimal?

@Html.TextBoxFor(model => model, "{0:0.000}") //入力はカンマ区切りなし

大した修正ではないですが、知っておくと地味に役立ちます。