ASP.net MVC – 显示模板的集合

我在MVC中有以下模型:

public class ParentModel { public string Property1 { get; set; } public string Property2 { get; set; } public IEnumerable<ChildModel> Children { get; set; } } 

当我想要显示父模型的所有孩子时,我可以这样做:

 @Html.DisplayFor(m => m.Children) 

然后,我可以创build一个ChildModel.cshtml显示模板,DisplayFor将自动迭代列表。

如果我想为IEnumerable创build一个自定义模板呢?

 @model IEnumerable<ChildModel> <table> <tr> <th>Property 1</th> <th>Property 2</th> </tr> ... </table> 

如何创build一个具有IEnumerable<ChildModel>模型types的显示模板,然后调用@Html.DisplayFor(m => m.Children)而不抱怨模型types错误?

喜欢这个:

 @Html.DisplayFor(m => m.Children, "YourTemplateName") 

或者像这样:

 [UIHint("YourTemplateName")] public IEnumerable<ChildModel> Children { get; set; } 

显然你会有~/Views/Shared/DisplayTemplates/YourTemplateName.cshtml

 @model IEnumerable<ChildModel> <table> <tr> <th>Property 1</th> <th>Property 2</th> </tr> ... </table> 

这是对马斯洛的评论。 这是我第一次对SO做出贡献,所以我没有足够的评价 – 因此答复是答案。

您可以在ModelMetadataProvider中设置“TemplateHint”属性。 这会自动将任何IEnumerable连接到您指定的模板。 我只是在我的项目中尝试过。 下面的代码 –

 protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(CachedDataAnnotationsModelMetadata prototype, Func<object> modelAccessor) { var metaData = base.CreateMetadataFromPrototype(prototype, modelAccessor); var type = metaData.ModelType; if (type.IsEnum) { metaData.TemplateHint = "Enum"; } else if (type.IsAssignableFrom(typeof(IEnumerable<object>))) { metaData.TemplateHint = "Collection"; } return metaData; } 

你基本上覆盖了'CachedDataAnnotationsModelMetadataProvider'的'CreateMetadataFromPrototype'方法,并将你的派生types注册为首选的ModelMetadataProvider。

在您的模板中,您不能直接访问集合中元素的ModelMetadata。 我使用下面的代码来访问我的集合中的元素的ModelMetadata –

 @model IEnumerable<object> @{ var modelType = Model.GetType().GenericTypeArguments[0]; var modelMetaData = ModelMetadataProviders.Current.GetMetadataForType(null, modelType.UnderlyingSystemType); var propertiesToShow = modelMetaData.Properties.Where(p => p.ShowForDisplay); var propertiesOfModel = modelType.GetProperties(); var tableData = propertiesOfModel.Zip(propertiesToShow, (columnName, columnValue) => new { columnName.Name, columnValue.PropertyName }); } 

在我看来,我只需要调用@ Html.DisplayForModel()并加载模板。 没有必要在模型上指定“UIHint”。

我希望这是有价值的。

在我没有从视图中获取输出的问题中,我实际上已经有了一个如何用模型集合对模型进行模板化并将它们渲染的例子。

ASP.NET显示模板 – 无输出

实质上,您需要创build一个名为List<T>Collection<T>的模型,并使用它:

 @model ChildModelCollection @foreach (var child in Model) { Html.DisplayFor(m => child); } 

在您的集合模型迭代和呈现子级的模板中。 每个孩子都需要强types,所以你可能也想创build自己的项目模型types,并为这些模板。

所以对于OP问题:

 public class ChildModelCollection : Collection<ChildModel> { } 

将build立一个强types的模型,这个模型可以像任何其他模板一样被parsing为模板。

实际的“有效答案”是-IMHO-没有正确回答问题。 我认为OP正在寻找一种方法来创build一个没有指定UIHint的列表模板。

魔术的东西差不多就是这个工作

一些魔法加载了指定types的正确视图。
一些更多的魔法为指定types的集合加载相同的视图
应该有一些魔法迭代相同的视图为指定types的集合。

改变实际的行为?

打开你最喜欢的反汇编。 魔术发生在System.Web.Mvc.Html.TemplateHelpers.ExecuteTemplate 。 正如你所看到的,没有可扩展性来改变行为。 也许向MVC拉请求可以帮助…

去实际的魔术

我想出了一些有用的东西。 创build一个显示模板~/Views/Shared/DisplayTemplates/MyModel.cshtml

将模型声明为typesobject

如果对象是一个集合,则再次迭代并呈现模板。 如果它不是一个集合,那么显示该对象。

 @model object @if (Model is IList<MyModel>) { var models = (IList<MyModel>)Model; <ul> @foreach (var item in models) { @Html.Partial("DisplayTemplates/MyModel", item) } </ul> } else { var item = (MyModel)Model; <li>@item.Name</li> } } 

现在DisplayFor作品没有UIHint