我有一个ViewModel包装了两种复杂类型:
public class EditProductViewModel
{
public ProductData ProductData { get; set; }
public FridgeContent FridgeContent { get; set; }
}
这个视图:
@model EditProductViewModel
@using (Html.BeginForm("Edit", "ProductData", FormMethod.Post))
{
@Html.EditorForModel()
[...]
}
ProductData和FridgeContent包含POCO属性,数据注释如下:
public class FridgeContentMetadata : DatabaseEntityMetadataBase
{
[Required]
[HiddenInput(DisplayValue = false)]
public int ProductDataId { get; set; }
[Required]
[UIHint("StringReadOnly")]
public int ScaleId { get; set; }
[Required]
[UIHint("StringReadOnly")]
[Range(0.01, float.MaxValue, ErrorMessage = "The weight of a product must be positive.")]
public float Weight { get; set; }
[...]
}
我想在EditProductView中使用这些类的适当数据注释和EditorForModel()方法编辑ProductData和FridgeContent(我不想自己生成模板)。因此,我在/Views/Shared/EditorTemplates/:中创建了模板ProductData.cshtml和FridgeContent.cshtml
@model FridgeContent
@Html.EditorForModel()
遗憾的是,EditProductViewModel的视图为空(没有出现错误)。如果我单独对FridgeContent或ProductData使用EditorForModel,它可以正常工作。我还尝试将[UIHInt("..")]注释添加到EditProductViewModel中,但这并没有什么不同。
我错过了什么?
@model EditProductViewModel
@using (Html.BeginForm("Edit", "ProductData", FormMethod.Post))
{
@Html.EditorFor(o=> o.ProductData )
@Html.EditorFor(o=> o.FridgeContent )
}
或者为ViewModel创建一个包含这两行的编辑模板
@Html.EditorFor(o=> o.ProductData )
@Html.EditorFor(o=> o.FridgeContent )
升级:
哦,最终得到了它,因为渲染引擎在对象层次结构中只需要一步,你也可以在asp.net mvc代码中找到它。
在这里查看MVC 3.0源代码:
有一个名为DefaultEditorTemplates.cs
的文件,其中包含以下方法:
internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateHelperDelegate templateHelper) {
ViewDataDictionary viewData = html.ViewContext.ViewData;
TemplateInfo templateInfo = viewData.TemplateInfo;
ModelMetadata modelMetadata = viewData.ModelMetadata;
StringBuilder builder = new StringBuilder();
if (templateInfo.TemplateDepth > 1) { // DDB #224751
return modelMetadata.Model == null ? modelMetadata.NullDisplayText : modelMetadata.SimpleDisplayText;
}
foreach (ModelMetadata propertyMetadata in modelMetadata.Properties.Where(pm => ShouldShow(pm, templateInfo))) {
if (!propertyMetadata.HideSurroundingHtml) {
string label = LabelExtensions.LabelHelper(html, propertyMetadata, propertyMetadata.PropertyName).ToHtmlString();
if (!String.IsNullOrEmpty(label)) {
builder.AppendFormat(CultureInfo.InvariantCulture, "<div class="editor-label">{0}</div>rn", label);
}
builder.Append("<div class="editor-field">");
}
builder.Append(templateHelper(html, propertyMetadata, propertyMetadata.PropertyName, null /* templateName */, DataBoundControlMode.Edit, null /* additionalViewData */));
if (!propertyMetadata.HideSurroundingHtml) {
builder.Append(" ");
builder.Append(html.ValidationMessage(propertyMetadata.PropertyName));
builder.Append("</div>rn");
}
}
return builder.ToString();
}
它清楚地表明如果CCD_ 2只是呈现一个简单的文本。
正如上面的答案所示,这个问题似乎与框架限制了它将考虑的嵌套深度有关。
解决这个问题的一种方法是使用自己的编辑器模板。在Views/Shared/EditorTemplates
中创建局部视图Object.cshtml
。这里有一个模板示例:
@{
Func<ModelMetadata, bool> ShouldShow = metadata =>
metadata.ShowForEdit && !ViewData.TemplateInfo.Visited(metadata);
}
@if (ViewData.TemplateInfo.TemplateDepth > 5) {
if (Model == null) {
@ViewData.ModelMetadata.NullDisplayText
} else {
@ViewData.ModelMetadata.SimpleDisplayText
}
} else {
foreach (var prop in ViewData.ModelMetadata.Properties.Where(ShouldShow)) {
if (prop.HideSurroundingHtml) {
@Html.Editor(prop.PropertyName)
} else {
if (string.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString())==false) {
<div class="editor-label">
@Html.Label(prop.PropertyName)
</div>
}
<div class="editor-field">
@Html.Editor(prop.PropertyName)
@Html.ValidationMessage(prop.PropertyName)
</div>
}
}
}
在上面的示例中,您可以通过更改5
常量来设置最大嵌套深度。