如何在一个视图中使用两个IENumerable模型

时间:2014-01-06 15:58:21

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

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

这是我的代码。

型号:

    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的第一个参数    “

如何让它按预期工作?我的网上有很多像我这样的问题,但是找不到符合我的情况。

3 个答案:

答案 0 :(得分:7)

在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<T>时,没有索引器,所以这不起作用:

@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; }
}

答案 1 :(得分:0)

你需要像这样迭代它们:

@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()方法

答案 2 :(得分:0)

如果您传入任何类型的IEnumerable<>,通常需要遍历每个项目。由于您构建了一个半复杂模型,因此您需要在每个列表中显示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