しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC 3 開発入門 (15) - ビューの実装 (Delete, Index アクション)

ASP.NET MVC 3 開発入門 - インデックス

それでは残っていた Delete, Index アクションのビューを実装していきましょう。まずは Delete アクションのビューからです。

一般的な削除画面で要求されている機能は「削除しようとしているデータの内容表示」と「削除を行うボタン」の 2 つだと思いますが、実はスキャフォールディングで自動生成が可能になっています。それでは今回もまずはスキャフォールディングで生成されたコードを確認してみましょう。

@model MvcVideo.Models.Video

@{
    ViewBag.Title = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>
<fieldset>
    <legend>Video</legend>

    <div class="display-label">Title</div>
    <div class="display-field">@Model.Title</div>

    <div class="display-label">Description</div>
    <div class="display-field">@Model.Description</div>

    <div class="display-label">CreatedAt</div>
    <div class="display-field">@String.Format("{0:g}", Model.CreatedAt)</div>

    <div class="display-label">UpdatedAt</div>
    <div class="display-field">@String.Format("{0:g}", Model.UpdatedAt)</div>
</fieldset>
@using (Html.BeginForm()) {
    <p>
        <input type="submit" value="Delete" /> |
        @Html.ActionLink("Back to List", "Index")
    </p>
}

最初の方は Details ビューと同じように Model の中身を表示するコードになっていますが、最後にある Html.BeginForm で囲まれた部分が実際に削除を行うボタンになります。ここまで自動で生成してくれますので、あとは本当にデザインに合わせて修正する程度で済んでしまいます。

特に何もすることなく Delete ビューに関しては完成してしまいました。実際に表示すると以下のようになります。

Delete ボタンを押すと削除がちゃんと行われます。

それでは最後に Index アクションのビューを実装していきましょう。機能的には登録されている動画の一覧表示になりますので、スキャフォールディングでは List を使って生成することになります。しかし、一覧表示では一般的にページングが要求されますので、対応を行うために少しだけリポジトリにも手を入れましょう。

それではスキャフォールディングで作成されたコードを確認しましょう。

@model IEnumerable<MvcVideo.Models.Video>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th></th>
        <th>
            Title
        </th>
        <th>
            Description
        </th>
        <th>
            CreatedAt
        </th>
        <th>
            UpdatedAt
        </th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.VideoId }) |
            @Html.ActionLink("Details", "Details", new { id=item.VideoId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.VideoId })
        </td>
        <td>
            @item.Title
        </td>
        <td>
            @item.Description
        </td>
        <td>
            @String.Format("{0:g}", item.CreatedAt)
        </td>
        <td>
            @String.Format("{0:g}", item.UpdatedAt)
        </td>
    </tr>
}

</table>

スキャフォールディングで生成しただけでも、以下のようにちゃんと一覧画面としての動作は行えていますが、これから動画数が増えていくことを考慮するとページングは必要となります。

ではどうやって実装するかですが、ASP.NET MVC 3 にはそういった機能はありません。実際のところ MVC フレームワークが行うべき仕事ではないので、MVC 1 の頃から様々な実装方法が提案されていますが、今回は「NerdDinnerステップ8:ページングのサポート − @IT」などで利用されている PaginatedList クラスを使う方法を採用します。

とりあえず PaginatedList を Models ディレクトリ内に新しくファイルを追加して作成してください。その後は IVideoController と VideoController の GetPagedList メソッドを以下のように修正します。

public PaginatedList<Video> GetPagedList(int page, int count)
{
    return new PaginatedList<Video>(_context.Videos.OrderBy(p => p.CreatedAt), page, count);
}

インターフェースも戻り値の型を修正するのを忘れないでください。リポジトリ作った時にやっておけという話ですが、今回は後からになってしまいました。
注意点としては Skip と Take 拡張メソッドを使うためにはソートされている必要があるということです。なので PagenatedList のコンストラクタには OrderBy でソートしたクエリを指定しています。

モデルの修正は終わりましたので、今度はビューの修正を行いましょう。1 つ目は @model で指定している型です。

@* PagenatedList に変更する *@
@model MvcVideo.Models.PaginatedList<MvcVideo.Models.Video>

Model の型を変えたので他にも変える必要があるんじゃないかと思いますが、PagenatedList は IEnumerable を実装しているので、foreach もそのまま動作しますので変更の必要はありません。

後はページャを実装すれば Index ビューは完成となります。今回はページャを以下のように実装しました。

@if (Model.HasPreviousPage)
{
    @Html.ActionLink("<<<", null, new { page = (Model.PageIndex - 1) })
}
 
@if (Model.HasNextPage)
{ 
    @Html.ActionLink(">>>", null, new { page = (Model.PageIndex + 1) })
}

それでは動作確認をしてみましょう。大量のダミーデータを入れるのは大変なので、1 ページの表示件数を減らしてページングが行われるようにしました。

テーブル下の ">>>" をクリックすると…

ちゃんとページングが行われました!

これで動画周りのビューは全て実装が終わりましたが、タグとコメントの登録に関してはまだフォームを用意していませんので、次回以降に追加を行います。お疲れ様でした。