如何使用3个字段为DateTime创建编辑器模板?

时间:2011-07-14 12:28:46

标签: c# asp.net-mvc asp.net-mvc-3 editortemplates

我想为DateTime创建一个编辑器模板,我需要3个独立的字段:

(DropDown) Day    |    (DropDown) Month    |    (DropDown) Year

我如何以及在何处创建此文件?当我发布到控制器时,我需要做些什么来将这3个字段转换为单个DateTime

5 个答案:

答案 0 :(得分:3)

Scott Hanselman有blog post创建自定义模型绑定器来处理DateTime。它并不完全适合你的场景,但它应该给你一些想法,一旦它到位,编辑器模板应该更容易......

就创建文件时放置文件的位置而言 - 这很容易:

~/Views/Shared/EditorTemplates/DateTime.[ascx|cshtml|vbhtml]

答案 1 :(得分:3)

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

注意这个解决方案很容易放入,而不需要使用Custom ModelBinder,因为我们构造了一个包含完整日期时间的表单值。但是,这确实意味着

  1. 您依赖于启用了javascript的客户端,
  2. 您需要在母网页中包含对jQuery库的脚本引用(例如<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
  3. 如果这是不可接受的,你将不得不看看@Jon指出的Custom ModelBinders。

答案 2 :(得分:1)

Editor Templates是你最好的选择。如果您希望从任何位置获得编辑器模板,请将其放在Views / Shared / EditorTemplates文件夹中。如果您希望所有DateTime类型都使用此模板,请创建名为DateTime的部分。如果您只想让其中一些模板使用此模板,则将其称为其他模板,然后使用UIHintAttribute属性创建一个编辑器模板,其名称与您为该属性使用的值相同。

要使模型绑定器继续工作,您可能需要向编辑器添加一些javascript,并且对于任何下拉下拉列表的更改应更新隐藏字段(具有正确的名称以便模型绑定器将起作用)月/日/年值。

答案 3 :(得分:0)

可能效率不高,但在您的视图模型中,您可以分别为日,月和年分别设置三个ints。然后,当您返回提交的视图模型时,您只需使用这三个字段即可构建DateTime对象。

就创建模板而言,我认为部分视图是最好的方法。不确定,我自己还在学习MVC。

答案 4 :(得分:0)

如果您使用的是html.editor,则可以通过在定义控件的views / shared / Editors中添加ascx文件来指定您自己的编辑器,并且将在该文件的后面代码中添加三个字段。