我想为DateTime
创建一个编辑器模板,我需要3个分隔字段:
(DropDown) Day | (DropDown) Month | (DropDown) Year
我如何以及在哪里创建这个文件?当我发布到控制器时,我需要做些什么来把这3个字段变成一个DateTime
?
在Views/Shared/EditorTemplates
文件夹中创建一个名为DateTime.ascx
的部分视图。
<%@ 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,因为我们构造了一个包含完整日期时间的单一表单值。然而,这并不意味着
- 您依赖于启用javascript的客户端,并且
- 你需要在你的主页中包含一个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文件来指定自己的编辑器,该文件定义了控件,并且三个字段的添加将在该文件后面的代码中完成。