自動生成されたアプリケーションの修正

自動生成されたソースコードに手を加え、より見栄え良くなるように修正します。



共通Viewの修正

以下の修正を行います。

  • タイトルを "薬品情報検索" に変更
  • タイトルクリック時に Drugs/Index に遷移するよう修正
  • フッターの名称を修正



_Layout.cshtml

@{
    ViewBag.ApplicationName = "薬品情報検索";
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - @ViewBag.ApplicationName</title>
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink((string)ViewBag.ApplicationName, "Index", "Drugs", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                </ul>
            </div>
        </div>
    </div>

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - @ViewBag.ApplicationName</p>
        </footer>
    </div>

    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>



Indexの修正

以下の修正を行います。

  • 項目名を日本語化する
  • 薬効分類コードに名称を併記する



メタデータクラスの追加

メタデータクラス を使用して Drugs, ClassificationsDisplayName を設定します。


Models/DrugsMetadata.cs

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace WebApplication1.Models
{
    [MetadataType(typeof(DrugsMetadata))]
    public partial class Drugs
    {
    }

    public class DrugsMetadata
    {
        [DisplayName("薬品ID")]
        public int DrugId { get; set; }

        [DisplayName("薬品コード")]
        public string DrugCode { get; set; }

        [DisplayName("薬品名")]
        [Required(ErrorMessage = "薬品名は必須項目です。")]
        public string Name { get; set; }

        [DisplayName("会社名")]
        public string Company { get; set; }
    }
}



Models/ClassificationsMetadata.cs

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace WebApplication1.Models
{
    [MetadataType(typeof(ClassificationsMetadata))]
    public partial class Classifications
    {
    }

    public class ClassificationsMetadata
    {
        [DisplayName("薬効分類ID")]
        public int ClassificationId { get; set; }

        [DisplayName("薬効分類コード")]
        [Required(ErrorMessage = "薬効分類コードは必須項目です。")]
        [StringLength(3, ErrorMessage = "薬効分類コードは3桁以内で入力してください。")]
        public string ClassificationCode { get; set; }

        [DisplayName("薬効分類")]
        [Required(ErrorMessage = "薬効分類名称は必須項目です。")]
        public string Name { get; set; }
    }
}



用語解説: partial class

partial キーワードによって、クラスや構造体、メソッドの定義を複数のソースファイルに分割できます。

ここでは、EntityFramework で自動生成したモデルクラスに メタデータクラスの定義を追加する目的で使用しています。

部分クラスと部分メソッド


用語解説: MetadataType

MetadataType 属性は 指定したクラス (メタデータクラス) と 自身の名称が一致するプロパティについて、メタデータクラスの属性を適用します。

これにより、自動生成されたモデルクラスに手を入れることなく DisplayName などの属性を定義することができます。

メタデータクラス の名称は何でも構いませんが わかりやすさから、対象モデルクラス名 + Metadata とするのが慣習です。




Viewの修正

薬効分類コードだけでなく、名称を併記するように修正します。

また、th タグに class="col-xs-N" を指定して、各列の幅を調整しています。
(class の詳細については Bootstrap - Grid system を参照してください。)


Views/Drugs/Index.cshtml

@model IEnumerable<WebApplication1.Models.Drugs>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th class="col-xs-1">
            @Html.DisplayNameFor(model => model.DrugCode)
        </th>
        <th class="col-xs-4">
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th class="col-xs-2">
            @Html.DisplayNameFor(model => model.Company)
        </th>
        <th class="col-xs-3">
            @Html.DisplayNameFor(model => model.Classifications.Name)
        </th>
        <th class="col-xs-2"></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.DrugCode)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Company)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Classifications.ClassificationCode) :
            @Html.DisplayFor(modelItem => item.Classifications.Name)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.DrugId }) |
            @Html.ActionLink("Details", "Details", new { id=item.DrugId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.DrugId })
        </td>
    </tr>
}

</table>



補足解説: Razor での model, Model, modelItem

@model ディレクティブはそのViewファイルに渡されるデータ (コントローラーの View メソッドの引数) の型を表します。

コントローラーの View メソッドで渡されてきたデータは Model というプロパティに格納されます。
Index.cshtml の場合は Drugs のリストが格納されています。

HTMLヘルパーメソッド では、特にコード上で指定していませんが、 Model の内容を ヘルパーに指定された ラムダ式 の引数として渡します。


DisplayNameFor のラムダ式で指定されている model には Drugs クラスが入ります。

DisplayNameFor で必要なのはモデルクラスの Metadata なので、リストが渡されてきた場合でも モデルクラスから Metadata を参照して DisplayName を返します。


DisplayFor では、モデルクラスに格納されているデータが必要となります。

ラムダ式の modelItem には Model (Drugsのリスト) が渡されてきますが それは使用せず、foreach で取り出した item のプロパティを参照しています。




Details の修正

薬効分類コードのみ表示されているので、名称も表示するように修正します。

Views/Drusg/Details.cshtml

@model WebApplication1.Models.Drugs

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
    <h4>Drugs</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.DrugCode)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.DrugCode)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Company)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Company)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Classifications.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Classifications.ClassificationCode) :
            @Html.DisplayFor(model => model.Classifications.Name)
        </dd>

    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.DrugId }) |
    @Html.ActionLink("Back to List", "Index")
</p>



Create の修正

コンボボックスに薬効分類コードのみ表示されているので、名称も表示するように修正します。


コントローラーの修正

Drugs/CreateGET に対応するアクションメソッドを修正します。


Controllers/DrugsController.cs

// GET: Drugs/Create
public ActionResult Create()
{
    ViewBag.ClassificationId = db.Classifications.Select(item => new SelectListItem
    {
        Text = item.ClassificationCode + ":" + item.Name,
        Value = item.ClassificationId.ToString()
    });

    return View();
}

SelectListItem はコンボボックスの各要素を表します。
Text に 薬効分類コードと名称を、 Value に ID を指定しています。



Viewの解説

@Html.DropDownList() は第2引数に null を渡した場合、 ViewBag に 第1引数と同じキーの項目があれば、それをセットしてくれます。

ViewBag の項目名は変更していないので、Create.cshtml には何も変更を行わなくとも期待する動作となります。



Edit の修正

コンボボックスに薬効分類コードのみ表示されているので、名称も表示するように修正します。


コントローラーの修正

Create と同様、コンボボックスの各要素の生成処理を修正します。


Controllers/DrugsController.cs

// GET: Drugs/Edit/5
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Drugs drugs = db.Drugs.Find(id);
    if (drugs == null)
    {
        return HttpNotFound();
    }

    ViewBag.ClassificationId = db.Classifications.Select(item => new SelectListItem
    {
        Text = item.ClassificationCode + ":" + item.Name,
        Value = item.ClassificationId.ToString(),
        Selected = item.ClassificationId == drugs.ClassificationId
    });

    return View(drugs);
}


Selected = item.ClassificationId == drugs.ClassificationId は コンボボックスの初期値の指定です。



Viewの解説

自動生成されたソースコードで DropDownListFor を使用していないのは、初期選択値を渡せないためです。



Delete の修正

薬効分類コードのみ表示されているので、名称も表示するように修正します。

また、確認メッセージが英語になっているので、日本語に変更します。


Views/Drugs/Delete.cshtml

@model WebApplication1.Models.Drugs

@{
    ViewBag.Title = "Delete";
}

<h2>Delete</h2>

<h3>以下のデータを削除します。よろしいですか?</h3>
<div>
    <h4>Drugs</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.DrugCode)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.DrugCode)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Company)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Company)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Classifications.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Classifications.ClassificationCode) :
            @Html.DisplayFor(model => model.Classifications.Name)
        </dd>

    </dl>

    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()

        <div class="form-actions no-color">
            <input type="submit" value="Delete" class="btn btn-default" /> |
            @Html.ActionLink("Back to List", "Index")
        </div>
    }
</div>





自動生成されたアプリケーションの修正について解説しました。

今回は見た目の修正を行いましたが、次回は機能の追加・修正について解説します。




次へ