7

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

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

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

4

5 回答 5

3

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

就创建文件后放置文件的位置而言 - 这很简单:

~/Views/Shared/EditorTemplates/DateTime.[ascx|cshtml|vbhtml]
于 2011-07-14T13:00:44.740 回答
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隐藏字段的使用。

请注意,此解决方案无需费心使用自定义 ModelBinders 即可轻松加入,因为我们构建了包含完整日期时间的单个表单值。然而,这确实意味着

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

如果这不可接受,您将不得不查看 @Jon 所指出的自定义 ModelBinders。

于 2011-07-14T13:45:12.190 回答
1

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

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

于 2011-07-14T13:00:14.833 回答
0

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

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

于 2011-07-14T12:54:03.570 回答
0

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

于 2011-07-14T13:02:26.093 回答