Как создать шаблон редактора для DateTime с 3 полями? - PullRequest
7 голосов
/ 14 июля 2011

Я хочу создать шаблон редактора для DateTime, мне нужно 3 отдельных поля:

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

Как и где я могу создать этот файл? И что мне нужно сделать, чтобы превратить эти 3 поля в одно DateTime при публикации на контроллере?

Ответы [ 5 ]

3 голосов
/ 14 июля 2011

В вашей папке 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) : "") %>

, который создает шаблон редактора со скрытымполе, содержащее представление ISO 8601 даты, которую MVC ModelBinder может проанализировать.

jQuery обновляет скрытое поле при каждом изменении раскрывающихся списков.Обратите внимание на использование ViewData.TemplateInfo.HtmlFieldPrefix, которое я использую для получения сгенерированного id скрытого поля.

Обратите внимание , что это решение легко внедряется, не обращая внимания на Custom ModelBinders, потому что мысоздать единственное значение формы, содержащее полную дату и время.Тем не менее, это означает, что

  1. Вы полагаетесь на клиент с включенным javascript, и
  2. Вам необходимо включить ссылку на скрипт на библиотеку jQuery на главной странице (например, <script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>)

Если это не приемлемо, вам придется посмотреть на Custom ModelBinders, как указывал @Jon.

3 голосов
/ 14 июля 2011

Скотт Хансельман имеет сообщение в блоге о создании пользовательского механизма связывания моделей для обработки DateTime с.Он не совсем соответствует вашему сценарию, но должен дать вам некоторые идеи, и как только он будет создан, шаблон редактора станет намного проще ...

С точки зрения того, где разместить файл после его создания -это легко:

~/Views/Shared/EditorTemplates/DateTime.[ascx|cshtml|vbhtml]
1 голос
/ 14 июля 2011

Шаблоны редактора - ваш лучший выбор.Если вы хотите, чтобы шаблон редактора был доступен из любого места, поместите его в папку Views / Shared / EditorTemplates.Если вы хотите, чтобы все типы DateTime использовали этот шаблон, то создайте частичную часть с именем DateTime.Если вы хотите, чтобы только некоторые из них использовали этот шаблон, тогда назовите его как-нибудь еще, и используйте атрибут UIHintAttribute и создайте шаблон редактора с тем же именем, что и значение, которое вы используете для этого атрибута.

Комучтобы механизм связывания модели продолжал работать, вам может потребоваться добавить в редактор некоторый javascript, а onchange для любого из раскрывающихся списков должен обновить скрытое поле (с правильным именем, чтобы связыватель модели работал) с выбранным месяцем / днем ​​/значения года.

0 голосов
/ 14 июля 2011

если вы используете html.editorfor, вы можете указать свои собственные редакторы, добавив файл ascx в views / shared / Editors, который определяет элемент управления, и добавление трех полей будет сделано в коде этого файла.

0 голосов
/ 14 июля 2011

Вероятно, не самая эффективная, но в вашей модели представления у вас может быть три ints для дня, месяца и года соответственно. Затем, когда вы возвращаете отправленную модель представления, вы можете просто использовать три поля для создания DateTime объекта.

Что касается создания шаблона, я думаю, что частичный вид будет лучшим способом. Не уверен, я все еще изучаю MVC.

...