【问题标题】:How to use two IENumerable models in one view如何在一个视图中使用两个 IENumerable 模型
【发布时间】:2014-01-06 15:58:21
【问题描述】:

我试图在一个视图中使用两个模型,但据我了解,我的程序在模型中看不到任何对象。

这是我的代码。

型号:

    public class Album
    {
        [Key]
        public int ThreadId { get; set; } 
        public int GenreId { get; set; }
        public string Title { get; set; }
        public string ThreadByUser { get; set; } 
        public string ThreadCreationDate { get; set; }
        public string ThreadContent { get; set; } 
        public Genre Genre { get; set; }
        public List<Posts> Posty { get; set; }
    }
    public class Posts 
    {
        [Key]
        public int PostId { get; set; }
        public int ThreadId { get; set; } 
        public string PostTitle { get; set; }
        public string PostContent { get; set; }
        public string PostDate { get; set; }
        public string PosterName { get; set; }
        public Album Album { get; set; }

    }

    public class ModelMix
    {
        public IEnumerable<Posts> PostsObject { get; set; }
        public IEnumerable<Album> ThreadsObject { get; set; }
    }  

索引控制器代码:

    public ActionResult Index(int id)
    {

        ViewBag.ThreadId = id;
        var posts = db.Posts.Include(p => p.Album).ToList();
        var albums = db.Albums.Include(a => a.Genre).ToList();

        var mixmodel = new ModelMix
        {
            PostsObject = posts,
            ThreadsObject = albums
        };

        return View(mixmodel);
    }

查看代码:

@model MvcMusicStore.Models.ModelMix

<h2>Index</h2>

@Html.DisplayNameFor(model => model.PostsObject.PostContent)

当我尝试执行我的程序时,我收到了这个错误:

CS1061:“ System.Collections.Generic.IEnumerable '不包含定义 “PostContent”的未找到扩展“PostContent”的方法,其中 接受类型为“System.Collections.Generic.IEnumerable”的第一个参数 "

我怎样才能让它按预期工作?网上有很多类似我的问题,但我找不到任何符合我的情况。

【问题讨论】:

  • 你需要在 for\foreach 中迭代它们

标签: asp.net-mvc asp.net-mvc-4 model ienumerable


【解决方案1】:

在 MVC 中开始循环模型可能会有点混乱,只是因为可以为模板化帮助器(即Html.DisplayForHtml.EditorFor)提供模板,帮助器将自动为集合中的每个元素调用这些模板。这意味着,如果您是 MVC 新手,并且没有意识到尚未为该集合提供 DisplayTemplateEditorTemplate,那么看起来很简单:

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

就是你所需要的。因此,如果您已经看过类似的东西,那可能就是您假设它会起作用的原因。但是,让我们暂时假设没有提供模板。你有两个选择。

首先,最简单的方法是在集合上使用foreach

@foreach (var post in Model.PostsObject)
{
    @Html.DisplayFor(m => post.PostTitle)
    // display other properties
}

您也可以使用for 循环,但使用IEnumerable&lt;T&gt;,没有索引器,所以这不起作用:

@for (int i = 0; i < Model.PostsObject.Count(); i++)
{
    // This generates a compile-time error because
    // the index post[i] does not exist.
    // This syntax would work for a List<T> though.
    @Html.DisplayFor(m => post[i].PostTitle)
    // display other properties
}

如果你还想使用for 循环,你可以像这样使用它:

@for (int i = 0; i < Model.PostsObject.Count(); i++)
{
    // This works correctly
    @Html.DisplayFor(m => post.ElementAt(i).PostTitle)
    // display other properties
}

所以使用你喜欢的任何一个。但是,在某些时候,考虑提供templates for your types 是个好主意。 (注意:尽管本文是为 MVC 2 编写的,但建议仍然适用。)它们允许您从视图中删除循环逻辑,使它们保持清洁。当与Html.DisplayForHtml.EditorFor 结合使用时,它们还将为模型绑定生成正确的元素命名(这很棒)。它们还允许您重复使用类型的表示。

我要说的最后一条评论是您的属性的命名有点冗长:

public class ModelMix
{
    public IEnumerable<Posts> PostsObject { get; set; }
    public IEnumerable<Album> ThreadsObject { get; set; }
}

我们已经知道它们是对象,因此无需在最后添加。这更具可读性:

public class ModelMix
{
    public IEnumerable<Posts> Posts { get; set; }
    public IEnumerable<Album> Threads { get; set; }
}

【讨论】:

  • 非常感谢,我使用了 foreach 循环。我不知道我的问题的解决方案会这么简单!
【解决方案2】:

你需要像这样迭代它们:

@model MvcMusicStore.Models.ModelMix

<h2>Index</h2>

@for(var i=0; i<model.PostsObject.Count(); i++)
{
    @Html.DisplayNameFor(model => model.PostsObject[i].PostContent)
}

而且最好保存 IList 而不是 IEnumerable,因为它将具有 Count 属性,而不是使用 Count() 方法

【讨论】:

  • DisplayNameFor 将只显示标题而不显示实际数据。这些通常用于表的标题。
  • 是的,我知道。但最初的问题是关于 DisplayNameFor 方法的,所以用它制作了样本
【解决方案3】:

如果您传入任何类型的IEnumerable&lt;&gt;,通常需要遍历每个项目。由于您构建了一个半复杂模型,因此您需要在每个列表中显示 foreach 项目。这是一个基于 ASP.NET MVC 教程的示例,我认为它会对您有所帮助:

@model IEnumerable<ContosoUniversity.Models.Course>

@{
    ViewBag.Title = "Courses";
}

<h2>Courses</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.CourseID)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Title)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Credits)
        </th>
        <th>
            Department
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.CourseID)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Credits)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Department.Name)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.CourseID }) |
            @Html.ActionLink("Details", "Details", new { id=item.CourseID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.CourseID })
        </td>
    </tr>
}

</table>

通常大多数人使用ICollection 作为他们的列表,其中示例可能位于对象中:

public virtual ICollection<Post> Posts { get; set; }

来源: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application

我建议从头开始,因为它可以帮助您理解为什么需要这样做: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc

【讨论】:

  • 这适用于我只有一个模型的情况,我确实知道它是如何工作的(我认为),我已经完成了该站点的教程(但对于 mvc4 - 你制作电影数据库的那个) ,但他们没有包含在一个视图中包含两个模型的任何示例。
  • 您可以简单地从复杂对象中决定您想要哪个模型。 IE。 Model.Object1.Whatever / Model.Object2.Whatever
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多