[英]Razor view with nested model class
I have a nested class such as : 我有一个嵌套类,如:
public class Jar
{
public IEnumerable<NailClippings> Nails { set; get; }
public IEnumerable<People> Donors { set; get; }
}
My controller passes a single Jar
to my view, string typed as 我的控制器将一个
Jar
传递给我的视图,字符串键入为
@model Test.ViewModels.Jar
I can loop through the contents of Nails
and Donors
easily with something like this 我可以通过这样的东西轻松地遍历
Nails
和Donors
的内容
@foreach(var item in Model.Nails)
My issue is with using HTML helpers to generate Display names for me 我的问题是使用HTML帮助程序为我生成显示名称
@Html.DisplayNameFor(model => model.Nails.Length)
I have come up with a solution by changing the type of the inner nested classes to List
, appending .ToList()
at the end of my queries and changing the line to 我通过将内部嵌套类的类型更改为
List
,在查询结束时附加.ToList()
并将行更改为
@Html.DisplayNameFor(model => model.Nails[0].Length)
Being forced to use List
and have an index [0]
to display a name is goofy to me. 被迫使用
List
并使用索引[0]
来显示名称对我来说太愚蠢了。 Is there an alternative method for referencing inner nested class attributes? 是否有另一种引用内部嵌套类属性的方法?
Edit : View 编辑 :查看
<table>
<tr>
<th>@Html.DisplayNameFor(model => model.Nails[0].Length)</th>
.
.
</tr>
@foreach(var item in Model.Nails){
<tr>
<td>@Html.DisplayFor(modelItem => item.Length</td>
.
.
</tr>
}
</table>
You don't need to be writing any loops in your views. 您不需要在视图中编写任何循环。 It makes them so ugly.
这让他们变得如此丑陋。
Simply define a corresponding display template for the collection type. 只需为集合类型定义相应的显示模板即可。 So for example you would create
~/Views/Shared/DisplayTemplates/NailClippings.cshtml
partial view that will be strongly typed to a single element of the collection: 因此,例如,您将创建
~/Views/Shared/DisplayTemplates/NailClippings.cshtml
部分视图,该视图将强烈类型~/Views/Shared/DisplayTemplates/NailClippings.cshtml
集合的单个元素:
@model NailClippings
<tr>
<td>
@Html.DisplayFor(x => x.Length)
</td>
.
.
</tr>
and now inside your main view it's as simple as: 现在在主视图中,它很简单:
@model Jar
<table>
<thead>
<tr>
<th>Length</th>
.
.
</tr>
</thead>
<tbody>
@Html.DisplayFor(x => x.Nails)
</tbody>
</table>
Display/editor templates work by convention. 显示/编辑器模板按惯例工作。 So here when inside your main view you use
@Html.DisplayFor(x => x.Nails)
, ASP.NET MVC will analyze the type of the Nails
property and will see that it is an IEnumerable<NailClippings>
collection. 因此,当您在主视图中使用
@Html.DisplayFor(x => x.Nails)
,ASP.NET MVC将分析Nails
属性的类型,并将看到它是一个IEnumerable<NailClippings>
集合。 So it will start looking for a corresponding display template first inside ~/Views/CurrentController/DisplayTemplates/NailClippings.cshtml
, then inside ~/Views/Shared/DisplayTemplates/NailClippings.cshtml
and finally it will fallback to the default display template
. 因此它将首先在
~/Views/CurrentController/DisplayTemplates/NailClippings.cshtml
内部开始寻找相应的显示模板,然后在~/Views/Shared/DisplayTemplates/NailClippings.cshtml
,最后它将回~/Views/Shared/DisplayTemplates/NailClippings.cshtml
default display template
。 When a template is selected this template will automatically be executed for you by ASP.NET MVC for each element of the collection property so that you never have to worry about things like writing some loops in your views, worry about indexes, ... 当选择模板时,ASP.NET MVC将为集合属性的每个元素自动为您执行此模板,这样您就不必担心在视图中编写一些循环,担心索引,......
This also works with editor templates: @Html.EditorFor(x => x.Nails)
will look for ~/Views/Shared/EditorTemplates/NailClippings.cshtml
. 这也适用于编辑器模板:
@Html.EditorFor(x => x.Nails)
将查找~/Views/Shared/EditorTemplates/NailClippings.cshtml
。 The bonus you get here is that the generated input fields will have correct names and you when you submit the form, the default model binder will automatically rehydrate your view model that the HttpPost action is taking as argument from the request. 您获得的奖励是生成的输入字段将具有正确的名称,并且当您提交表单时,默认模型绑定器将自动为您的视图模型重新水化HttpPost操作作为请求的参数。
Basically if you respect the conventions that the framework is following you will make your life much easier. 基本上,如果您尊重框架遵循的惯例,您将使您的生活更轻松。
Instead of 代替
model.Nails[0].Length
You could use 你可以用
model.Nails.First().Length
Without having to convert to a List
. 无需转换为
List
。
I think you can just use item
variable of loop 我想你可以只使用循环的
item
变量
@Html.DisplayNameFor(model => item.Length)
UPDATE another option for you is creating partial view for Nails displaying. 更新另一个选项是为Nails显示创建局部视图。 It will be strongly typed to
IEnumerable<NailClippings>
and all properties will be available: 它将被强类型
IEnumerable<NailClippings>
并且所有属性都可用:
@Html.Partial("_Nails", Model.Nails)
Nails partial view: 指甲局部视图:
@model IEnumerable<NailClippings>
<table>
<tr>
<th>@Html.DisplayNameFor(model => model.Length)</th>
.
.
</tr>
@foreach(var item in Model){
<tr>
<td>@Html.DisplayFor(modelItem => item.Length)</td>
.
.
</tr>
}
</table>
I think this sample code is useful for nested model class 我认为这个示例代码对嵌套模型类很有用
@model ViewModels.MyViewModels.Theme
@Html.LabelFor(Model.Theme.name)
@foreach (var category in Model.Theme)
{
@Html.LabelFor(category.name)
@foreach(var product in theme.Products)
{
@Html.LabelFor(product.name)
@foreach(var order in product.Orders)
{
@Html.TextBoxFor(order.Quantity)
@Html.TextAreaFor(order.Note)
@Html.EditorFor(order.DateRequestedDeliveryFor)
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.