1つのビューで2つのモデルを使用しようとしていますが、私の理解では、プログラム内にオブジェクトが表示されません。
これが私のコードです。
モデル:
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」タイプの最初の引数を取ります。
どうすれば意図したとおりに機能させることができますか?インターネット上に私のような質問がたくさんありますが、私の場合に一致するものは見つかりませんでした。
テンプレート化されたヘルパー(つまり、Html.DisplayFor
とHtml.EditorFor
)に、コレクション内のすべての要素に対してヘルパーが自動的に呼び出すテンプレートを提供できるため、MVCでモデルをループすることは、最初は少し混乱する可能性があります。つまり、MVCを初めて使用し、コレクションにDisplayTemplate
またはEditorTemplate
がまだ提供されていないことに気付いていない場合は、単純なように見えます。
@Html.DisplayFor(m => m.SomePropertyThatHoldsACollection)
は、あなたが必要とすることすべてです。したがって、そのようなものをすでに見たことがあれば、それが機能すると仮定した理由かもしれません。ただし、しばらくの間、テンプレートが提供されていないと仮定しましょう。 2つのオプションがあります。
まず、最も簡単に言えば、コレクションに対して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
}
だからあなたが好きな方を使ってください。ただし、ある時点で、 タイプのテンプレート の提供を検討することをお勧めします。 (注:この記事はMVC 2向けに書かれていますが、アドバイスは引き続き適用されます。)ビューからループロジックを削除して、ビューをクリーンに保つことができます。 Html.DisplayFor
またはHtml.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; }
}
通常、任意のタイプのIEnumerable<>
を渡す場合は、各アイテムを反復処理する必要があります。半複雑なモデルを作成したので、各リストにforeach
アイテムを表示する必要があります。これは、ASP.NETMVCチュートリアルに基づいた例です。少し役立つと思います。
@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
次のように繰り返す必要があります。
@model MvcMusicStore.Models.ModelMix
<h2>Index</h2>
@for(var i=0; i<model.PostsObject.Count(); i++)
{
@Html.DisplayNameFor(model => model.PostsObject[i].PostContent)
}
また、Count()メソッドを使用する代わりに、Countプロパティを持つため、IEnumerableの代わりにIListを保存することをお勧めします。