我想为DateTime
创建一个编辑器模板,我需要3个独立的字段:
(DropDown) Day | (DropDown) Month | (DropDown) Year
我如何以及在何处创建此文件?当我发布到控制器时,我需要做些什么来将这3个字段转换为单个DateTime
?
答案 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,因为我们构造了一个包含完整日期时间的表单值。但是,这确实意味着
<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
)如果这是不可接受的,你将不得不看看@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文件来指定您自己的编辑器,并且将在该文件的后面代码中添加三个字段。