如何为带有3个字段的DateTime创建编辑器模板



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

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

我如何以及在哪里创建这个文件?当我发布到控制器时,我需要做些什么来把这3个字段变成一个DateTime ?

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

注意这个解决方案很容易使用,而不需要使用自定义modelbinder,因为我们构造了一个包含完整日期时间的单一表单值。然而,这并不意味着

  1. 您依赖于启用javascript的客户端,并且
  2. 你需要在你的主页中包含一个jQuery库的脚本引用(例如<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>)

如果这是不可接受的,您将不得不查看Custom modelbinder,如@Jon所指出的。

Scott Hanselman有一篇关于创建自定义模型绑定器来处理DateTime s的博客文章。它并不完全适合您的场景,但它应该给您一些想法,一旦它到位,编辑器模板应该更容易…

关于文件创建后放置的位置-这是简单的:

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

编辑器模板是你最好的选择。如果你想让编辑器模板在任何地方都可用,把它放在Views/Shared/EditorTemplates文件夹中。如果希望所有DateTime类型都使用此模板,则创建一个名为DateTime的部分。如果您只希望其中一些人使用此模板,则将其命名为其他名称,并使用UIHintAttribute属性并创建一个名称与该属性的值相同的编辑器模板。

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

可能不是最有效的,但是在视图模型中可以分别为日、月和年设置三个ints。然后,当您返回提交的视图模型时,您可以简单地使用这三个字段来构建DateTime对象。

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

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

最新更新