のエディタテンプレートを作成したいのですがDateTime
、3つの別々のフィールドが必要です。
(DropDown) Day | (DropDown) Month | (DropDown) Year
このファイルはどこでどのように作成しますか?DateTime
そして、コントローラーに投稿するときに、これら3つのフィールドを1つに変換するには、何をする必要がありますか?
のエディタテンプレートを作成したいのですがDateTime
、3つの別々のフィールドが必要です。
(DropDown) Day | (DropDown) Month | (DropDown) Year
このファイルはどこでどのように作成しますか?DateTime
そして、コントローラーに投稿するときに、これら3つのフィールドを1つに変換するには、何をする必要がありますか?
Scott Hanselmanは、を処理するカスタムモデルバインダーの作成に関するブログ投稿DateTime
をしています。それはあなたのシナリオに正確には適合しませんが、それはあなたにいくつかのアイデアを与えるはずです、そしてそれが配置されると、エディターテンプレートははるかに簡単になるはずです...
作成されたファイルをどこに配置するかという点では、これは簡単なことです。
~/Views/Shared/EditorTemplates/DateTime.[ascx|cshtml|vbhtml]
Views/Shared/EditorTemplates
フォルダに という部分ビューを作成しますDateTime.ascx
。
この EditorTemplate のコードは次のようになります。
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DateTime?>" %>
<%
string controlId = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('.', '_');
%>
<script type="text/javascript">
$(function () {
$('#<%: controlId %>_Day, #<%: controlId %>_Month, #<%: controlId %>_Year').live('change', function () { updateHiddenDate('<%: controlId %>'); });
$('#<%: controlId %>_Day').val('<%: Model.HasValue ? Model.Value.Day.ToString() : "" %>');
$('#<%: controlId %>_Month').val('<%: Model.HasValue ? Model.Value.Month.ToString() : "" %>');
$('#<%: controlId %>_Year').val('<%: Model.HasValue ? Model.Value.Year.ToString() : "" %>');
updateHiddenDate('<%: controlId %>');
});
function updateHiddenDate(hiddenDateId) {
$('#' + hiddenDateId).val($('#' + hiddenDateId + '_Year').val() + "-" + $('#' + hiddenDateId + '_Month').val() + "-" + $('#' + hiddenDateId + '_Day').val());
}
</script>
<select id="<%: controlId %>_Day">
<% for (int dayOrdinal = 1; dayOrdinal <= 31; dayOrdinal++)
{
Response.Write(string.Format("<option value=\"{0}\">{0}</option>", dayOrdinal));
}
%>
</select>
<select id="<%: controlId %>_Month">
<% for (int monthOrdinal = 1; monthOrdinal <= 12; monthOrdinal++)
{
Response.Write(string.Format("<option value=\"{0}\">{1}</option>", monthOrdinal, System.Globalization.DateTimeFormatInfo.CurrentInfo.MonthNames[monthOrdinal - 1]));
}
%>
</select>
<select id="<%: controlId %>_Year">
<% for (int yearOrdinal = DateTime.Now.Year - 5; yearOrdinal <= DateTime.Now.Year + 5; yearOrdinal++)
{
Response.Write(string.Format("<option value=\"{0}\">{0}</option>", yearOrdinal));
}
%>
</select>
<%: Html.Hidden("", Model.HasValue ? String.Format("{0:yyyy-MM-dd}", Model) : "") %>
これにより、MVC ModelBinder が解析できる日付の ISO 8601 表現を含む隠しフィールドを持つエディター テンプレートが作成されます。
ドロップダウンが変更されるたびに、jQuery は隠しフィールドを更新します。隠しフィールドViewData.TemplateInfo.HtmlFieldPrefix
の生成を取得するために使用するの使用に注意してください。id
完全な日時を含む単一のフォーム値を作成するため、このソリューションはカスタム ModelBinders をいじることなく簡単に導入できることに注意してください。ただし、これは次のことを意味します。
<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
)それが受け入れられない場合は、@Jon が指摘したようにカスタム ModelBinders を確認する必要があります。
エディターテンプレートが最善の策です。エディターテンプレートをどこからでも利用できるようにする場合は、Views / Shared/EditorTemplatesフォルダーに配置します。すべてのDateTime
タイプでこのテンプレートを使用する場合は、と呼ばれるパーシャルを作成しますDateTime
。一部の人だけにこのテンプレートを使用させたい場合は、それを別の名前で呼び出し、UIHintAttribute
属性を使用して、その属性に使用する値と同じ名前のエディターテンプレートを作成します。
モデルバインダーを引き続き機能させるには、エディターにJavaScriptを追加する必要がある場合があります。ドロップダウンのいずれかを変更すると、選択した月/日で非表示フィールド(モデルバインダーが機能するように正しい名前)が更新されます。 /年の値。
ints
おそらく最も効率的ではありませんが、ビューモデルでは、日、月、年にそれぞれ3つ持つことができます。次に、送信されたビューモデルを返すときに、3つのフィールドを使用してDateTime
オブジェクトを作成できます。
テンプレートを作成する限り、部分的なビューが最善の方法だと思います。よくわかりませんが、私はまだMVCを自分で学んでいます。
html.editorfor を使用している場合は、views/shared/Editors にコントロールを定義する ascx ファイルを追加することで、独自のエディターを指定できます。3 つのフィールドの追加は、そのファイルのコード ビハインドで行われます。