Ответ 1
Динамика не подходит для счета с ASP.NET MVC. Они напоминают мне о ViewBag
, и я ненавижу ViewBag
от самых глубоких тканей моего тела. Поэтому я бы принял другой подход.
Возьмем, например, следующую модель:
public class Criterion
{
public string Text { get; set; }
public object Value { get; set; }
}
Значение может быть любым типом, который вы хотите обработать.
Теперь у вас может быть контроллер, который заполняет эту модель:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new[]
{
new Criterion { Text = "some integer", Value = 2 },
new Criterion { Text = "some boolean", Value = true },
new Criterion { Text = "some string", Value = "foo" },
};
return View(model);
}
}
а затем соответствующий вид:
@model IList<Criterion>
@using (Html.BeginForm())
{
for (int i = 0; i < Model.Count; i++)
{
<div>
@Html.LabelFor(x => x[i], Model[i].Text)
@Html.EditorFor(x => x[i].Value, "Criterion_" + Model[i].Value.GetType().Name)
</div>
}
<button type="submit">OK</button>
}
Теперь для каждого типа, который вы хотите обработать, вы можете определить соответствующий шаблон редактора:
~/Views/Shared/EditorTemplates/Criterion_String.cshtml
:
@model string
@Html.TextBoxFor(x => x)
~/Views/Shared/EditorTemplates/Criterion_Boolean.cshtml
:
@model bool
@Html.CheckBoxFor(x => x)
~/Views/Shared/EditorTemplates/Criterion_Int32.cshtml
:
@model int
@{
var items = Enumerable
.Range(1, 5)
.Select(x => new SelectListItem
{
Value = x.ToString(),
Text = "item " + x
});
}
@Html.DropDownListFor(x => x, new SelectList(items, "Value", "Text", Model))
Очевидно, что отображение этой модели в представлении - это только первый шаг. Я полагаю, что вы захотите получить значения, введенные пользователем в действии контроллера POST для некоторой обработки. В этом случае необходимы небольшие адаптации. Нам нужно добавить настраиваемое связующее устройство, которое сможет создать экземпляр правильного типа во время выполнения и включить конкретный тип в скрытое поле для каждой строки. Я уже показал пример в this post
. Также обратите внимание в этом примере, что я использовал базовый класс вместо прямой работы с типом object
.