Первая часть, где мы остановились на рабочих выпадающих списках с нерабочей валидацией.

Для того, чтобы стандартная клиентская валидация заработала, нужно сделать следующее:

  1. Заполнить метаданные. Мы сделали это в прошлой части.
  2. Заполнить поля ViewData.TemplateInfo. В нашем случае – из TemplateInfo родительского действия.
  3. Отрендерить выпадающий список на основе метаданных и данных шаблона.

Изменения затронут только представление выпадающего списка.

ViewsListDropDown.cshtml

@model SelectList
@{
   
this
.ViewContext.ViewData.TemplateInfo.FormattedModelValue
        =
this
.ViewContext.ParentActionViewContext.ViewData.TemplateInfo.FormattedModelValue;
       
   
this
.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix
        =
this
.ViewContext.ParentActionViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;
}
@
Html.DropDownList(
   
""
,
   
this
.Model,
   
this.ViewData.ModelMetadata.NullDisplayText
    )

Важно: ни в коем случае нельзя подменять ссылку ViewData.TemplateInfo на объект из родительского контекста. ASP.NET MVC рендерит атрибуты валидации только для первого элемента управления с заданным именем. В нашем примере это приведет к отсутствию валидаторов у всех списков, кроме первого.

После этого валидаторы заработают, и даже слишком хорошо:

image

В стандартном валидаторе целочисленного формата есть баг – он учитывает только атрибут value у элементов списка, и не учитывает innerText. Т.е. выбранный на картинке выше <option>1992</option> он числом не считает.

Для обхода этого бага можно создать SelectList с явным указанием имен свойств для Text/Value:

ControllersListController.cs

public ActionResult Years()
{
   
int? selectedYear = this.ControllerContext.ParentActionViewContext.ViewData.Model as int
?;

   
var model = new SelectList(Enumerable.Range(1990, 20).Select(y => new
{ Value = y }),
       
"Value", "Value"
, selectedYear);

   
this
.ViewData.Model = model;
   
this.ViewData.ModelMetadata = this
.ControllerContext.ParentActionViewContext.ViewData.ModelMetadata;

   
return View("DropDown");
}

Некрасиво, но работает. Надеюсь, баг исправят в релизе :)

Исходный код к этой статье: MvcDropDowns2.zip. Требует ASP.NET MVC 3.0 RC2 для запуска.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>