【问题标题】:MVC 4: Displaying a List<> property on a viewMVC 4:在视图上显示 List<> 属性
【发布时间】:2013-08-10 20:07:01
【问题描述】:

我有一个像这样的类的模型

public class Feature
{
    public int ID { get; set; }
    public string Desc { get; set; }
    public List<Camera> { get; set; }
}

还有一个这样的:

public class Camera
{
    public int ID { get; set; }
    public string ModelName { get; set; }
    public List<Feature> Features { get; set; }
}

我为 Camera 模型制作了一个 Controller 和 View,并在他们的 Features 集合中添加了几个带有多个 Fe​​ature 对象的相机。

但是,当我渲染相机视图(索引、详细信息、编辑)时,我在任何地方都看不到“功能”字段。在 Index 和 Details 视图中,我希望将 Features 集合中的项目视为多行文本,每行一个项目。

请问如何?

戴夫

PS:我的下一个问题将涉及如何让 Edit 视图显示一个多选滚动列表,其中列出了 Feature 表中的所有项目以及当前相机的 Feature 项目。

【问题讨论】:

    标签: entity-framework asp.net-mvc-4


    【解决方案1】:

    只需使用 DisplayTemplate。

    为此,请在 ~/Views/Shared/ 中添加一个名为 DisplayTemplates 的文件夹,并添加一个名为 Feature.cshtml 的 PartialView。在新创建的 PartialView 中添加以下代码:

    @model Feature
    
    <li>@Model.Desc</li>
    

    然后在您的相机模型的视图中,执行以下操作:

    <ul>
         @Html.DisplayFor(e => e.Features)
    </ul>
    

    【讨论】:

    • 当我尝试这个时,我得到错误:找不到类型或命名空间名称“Feature”(您是否缺少 using 指令或程序集引用?)它如何“连接”第二个框中的代码到第一个框中的代码?我的意思是,当它看到 e.Features 时,它怎么知道它应该使用 Desc?
    • 至于找不到您的“功能”类的错误,请尝试将完整的命名空间放在您的功能类前面,例如:@model MyNamespace.Feature。至于第二个代码如何链接到第一个,在第一个代码中,您定义了 Feature 对象的显示方式(毕竟它是一个 DisplayTemplate)。在第二个中,您告诉 ASP.NET 显示您的相机的所有功能。由于您的 DisplayTemplate (Feature.cshtml) 位于您的文件夹“~/Views/Shared/ 中,因此它将用于显示所有需要的 Feature 类型的对象使用Html.DisplayFor()显示。
    • 我不得不使用 MyNamespace.Models.Feature 让它工作,但这是有道理的。感谢您解释挂钩。
    • 请再问一个问题... 在 DisplayTemplate 中,为什么模型第一行是小写,第二行是大写?有什么区别?
    • 在第一行,您使用 Razor 特殊语法 @model 定义模型的类型。在第二行,您调用视图的 Model 属性,其中包含模型的实例。
    【解决方案2】:

    很难说没有来自控制器的任何代码,但 Entity Framework 的一个非常常见的问题是忘记使用 .Include() 扩展方法。例如var cameras = db.Cameras.Include(c =&gt; c.Features).ToList(); 这将为您提供相机列表和相关功能以传递给您的视图。

    此外,如果您将 virtual 关键字添加到导航属性,实体框架可以执行“延迟加载”,它会在第一次访问时自动加载关联的项目(服务器端)。通常,大多数导航属性也将被定义为通用的。例如:

    public class Feature
    {
        public int ID { get; set; }
        public string Desc { get; set; }
    
        public virtual ICollection<Camera> Cameras { get; set; }
    }
    
    public class Camera
    {
        public int ID { get; set; }
        public string ModelName { get; set; }
        public virtual ICollection<Feature> Features { get; set; }
    }
    

    这允许您访问更大的扩展方法数组以进行过滤和排序。 IEnumerable 描述行为,而 List 是该行为的实现。当你使用IEnumerable 时,你给了编译器一个将工作推迟到以后的机会,可能会在此过程中进行优化。如果您使用List,您会强制编译器立即具体化结果。在您的情况下,使用 ICollection vs IEnumearable 是必要的,因为 IEnumerable 只允许列表浏览,而 ICollection 定义了实体框架内部使用的 CopyTo 方法。

    【讨论】:

    • 你是对的,没有 Include()... 但是当我使用“return View(db.Cameras.Include(c => c.Features).ToList());”在控制器中,我收到错误“指定的包含路径无效。EntityType 'MyApp.Models.Camera' 未声明名为 'Features' 的导航属性。”即使 Intellisense 会在其下拉列表中显示该属性,并且它的定义如上图所示。猜猜我错过了什么?
    • 实际上是我的错误,因为你有 2 个相互引用的集合,你需要使用 ICollection 而不是 IEnumerable。我会更新答案。
    猜你喜欢
    • 2015-11-02
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2020-09-06
    相关资源
    最近更新 更多