我们一直试图让编辑模板使用动态属性 - 无济于事。也许你们其中一个可以帮助我们。
这大致是我们的课程:
public class Criterion
{
...
public string Text { get; set; }
public dynamic Value { get; set; }
public Type Type { get; set; }
...
}
我们的剃刀视图获得了一个包含一系列部分的模型,每个部分都包含一系列标准。 (我们在运行时获得这些信息。)所有这些标准都应该以编辑模式显示 - 关于它们的实际类型:(摘录)
@for (int i = 0; i < model.Sections.Count(); i++)
{
for (int j = 0; j < model.Sections[i].Criteria.Count(); j++)
{
var criterion = model.Sections[i].Criteria[j];
var type = criterion.Type.Name;
var name = "Sections[" + i + "].Criteria[" + j + "].Value";
var criterionDisplayName = criterion.Text;
<label for="Sections_@(i)__Criteria_@(j)__Value">@criterionDisplayName</label>
@Html.Editor(name, type)
}
}
这会正确显示一个复选框,但它不会使用该值来正确设置复选框状态(如果criterion.Value为true则检查)。其他类型也是如此,例如ints
。
(它确实在POST请求后填写表单,但这是因为MVC使用临时模型来重新创建用户输入。)
我们已经尝试过并研究过:甚至可以将编辑器模板与dynamic
类型的属性一起使用?如果是的话 - 我们怎样才能让它发挥作用? (我们不希望根据可能的类型来识别。我们希望MVC框架根据实际类型使用正确的编辑器模板。)
答案 0 :(得分:16)
Dynamics与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
类型。