编辑器集合和命名模板

本文关键字:集合 编辑器 | 更新日期: 2023-09-27 18:04:19

我是MVC 5和ASP的新手。. NET, EF6,现在我有一个名为EditorTemplate的问题。

我的模型是这样的:

public partial class Product
{
    public int pid { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Filter> Filters{ get; set; }
}
public partial class Filter
{
    public bool isRemoveable { get; set; }
}

我有一个名为FiltersCustomEditor的编辑器模板,它看起来像这样:

@model IList<Filter>
@Html.EditorFor(modelItem => @Model[i].isRemoveable)

我的问题是现在在我的产品视图中我不能调用:

@Html.EditorFor(m => m.Filters, "FiltersCustomEditor")

我得到这个错误:

传递给字典的模型元素的类型是"System.Collections.Generic"。HashSet 1[Filter]". However, this dictionary requires a model item of type "System.Collections.Generic.IList 1[Filter] .]

所以我试着这样称呼它:

@Html.EditorFor(m => m.Filters.ToList(), "FiltersCustomEditor")

得到这个错误:

模板只能用于字段访问、属性访问、一维数组索引或带有单个参数的自定义indexerausdrcken。

如果我转换的ICollection在我的模型到一个列表,它工作完美。但是这是一个从实体框架生成的类,所以这里的改变会破坏EF的功能。

我认为这是命名模板的一个特殊问题。因为如果我做一个默认的编辑模板为一个单一的过滤器称为过滤器。CSHTML和调用

@Html.EditorFor(m => m.Filters)

ICollection在内部处理得很好,EditorFor为List中的每个对象调用Template。

但是一定有解决这个问题的办法。唯一有效的方法是将Template更改为

@model ICollection<Filter>
@Html.EditorFor(modelItem => @Model.ToList()[i].isRemoveable)

然后这样命名

 @Html.EditorFor(m => m.Filters, "FiltersCustomEditor")

但是我认为这确实是一个弱的解决方案,特别是对于性能,如果每个字段必须在访问之前将iccollection转换为List。

所以他们是一种解决方法还是我错过了什么?

编辑器集合和命名模板

您将ICollection<Filter>传递给模板,但模板中的模型是IList<Filter>,因此错误(ICollection<T>不是IList<T>)。然而,你的方法是不正确的。EditorFor()方法接受IEnumerable<T>,因此代码可以简化为

/Views/Shared/EditorTemplates/Filter.cshtml中(注意模板的命名必须与类的名称相同)

@model yourAssembly.Filter
@Html.CheckBoxFor(m => m.isRemoveable)
.... // add any other properties, labels etc of Filter

,然后在主视图中它只是

@model yourAssembly.Product
@using (Html.BeginForm())
{
  ....
  @Html.EditorFor(m => m.Filters)
}

EditorFor()方法将根据模板正确地为集合中的每个项目生成html(没有循环,没有传递集合等)

旁注:根据您的评论,您还可以在/Views/YourControllerName/EditorTemplates文件夹中放置与每个控制器相关的特定EditorTemplates。默认情况下,EditorFor()方法将首先搜索/Views/YourController/EditorTemplates。如果没有找到,它将搜索/Views/Shared/EditorTemplates。最后,如果没有找到,它将使用内置的默认模板(s)基于您的模型属性。