我想创建一个编辑器模板DateTime
,我需要 3 个单独的字段:
(DropDown) Day | (DropDown) Month | (DropDown) Year
如何以及在哪里创建此文件?DateTime
当我发布到控制器时,我需要做什么才能将这 3 个字段变成一个字段?
我想创建一个编辑器模板DateTime
,我需要 3 个单独的字段:
(DropDown) Day | (DropDown) Month | (DropDown) Year
如何以及在哪里创建此文件?DateTime
当我发布到控制器时,我需要做什么才能将这 3 个字段变成一个字段?
Scott Hanselman 有一篇关于创建自定义模型绑定器来处理DateTime
s 的博客文章。它不完全适合您的场景,但它应该给您一些想法,一旦到位,编辑器模板应该会容易得多......
就创建文件后放置文件的位置而言 - 这很简单:
~/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,并且任何下拉列表的 onchange 都应使用所选月/日更新隐藏字段(使用正确的名称,以便模型绑定器可以工作) /年值。
可能不是最有效的,但在您的视图模型中,您可以分别ints
为日、月和年设置三个。然后,当您返回提交的视图模型时,您可以简单地使用这三个字段来构建一个DateTime
对象。
至于创建模板,我认为局部视图是最好的方法。不确定,我自己还在学习 MVC。
如果您使用 html.editorfor,您可以通过在定义控件的 views/shared/Editors 中添加 ascx 文件来指定您自己的编辑器,并且三个字段的添加将在该文件后面的代码中完成。