概要
前回:【ASP.NET Core MVC】ASP.NET Core MVCであみだくじを作ってみる 3 (モデルの追加)
今回は、cssを使ってビューのレイアウトを作成していきます。
コントローラー間でのモデルデータの受け渡しも考えてみます。
コントローラー間でモデルを受け渡す
ASP.NET Core でのセッションとアプリの状態をざっと読み、TempDataを使うことにしました。
HomeControllerのIndexアクションに、モデルデータをTempDataにセットする処理を追加します。
using Newtonsoft.Json;
/// <summary>
/// HomeビューでPOSTした時のアクション
/// </summary>
/// <param name="name"></param>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
public IActionResult Index(string name, KujiModel model)
{
// 入力エラーがある時は何もしない
if (!ModelState.IsValid)
return View(model);
// [結果を設定する]ボタンを押下した場合
if (name == "set")
{
// くじの数が減った場合は、結果入力欄を減らす
while (model.NumberOfKuji < model.Result.Count)
{
model.Result.RemoveAt(model.Result.Count - 1);
}
// くじの数が増えた場合は、結果入力欄を増やす
while (model.NumberOfKuji > model.Result.Count)
{
model.Result.Add(new ResultModel());
}
return View(model);
}
TempData["kuji"] = JsonConvert.SerializeObject(model);
// くじコントローラーを呼ぶ
return RedirectToAction("Index", "Kuji");
}
TempData["kuji"] = model としたくなるところですが、オブジェクトはセットできないようです。
このため、JsonConvert.SerializeObjectでjson文字列に変換してからセットしました。
KujiController側で、TempData["kuji"]を受け取ります。
using Amidakuji.Models;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace Amidakuji.Controllers
{
public class KujiController : Controller
{
[HttpGet]
public IActionResult Index()
{
ModelState.Clear();
// 受け取ったTempDataからデータを取得する
var json = TempData["kuji"]?.ToString();
if (json != null)
{
var model = JsonConvert.DeserializeObject<KujiModel>(json);
return View(model);
}
return View(new KujiModel());
}
}
}
JsonConvert.DeserializeObjectで、json文字列をKujiModel型にデシリアライズしています。
デシリアライズ後のモデルをビューに渡すことで、Homeビューで入力したデータをKujiビューでも使えるようになります。
cssファイルを追加する
JavaScript、CSS、画像等の静的ファイルは、Webルート(既定ではwwwroot)ディレクトリに格納されています。
ASP.NET Core MVCでは、デフォルトのcssフレームワークとしてBootstrapが導入されていますが、
今回はオリジナルのcssを作ります。
ソリューションエクスプローラーの「wwwroot\css」を選択します。
右クリックでメニューを表示し、追加⇒新しい項目を選択します。
スタイルシートを選択します。ここでは、名前を「kuji.css」としました。
Home\Index.cshtmlやKuji\Index.cshtmlの<style>をcssに移動します。
各cshtmlの<style>~<\style>は削除しておきます。
/*あみだくじデータの設定領域*/
.kuji-items {
display: grid; /*グリッドレイアウトにする*/
grid-auto-columns: 100px; /*1列あたりの幅 100px*/
grid-auto-rows: 36px; /*1行あたりの高さ 30px*/
background-color: #99CCCC; /*背景色*/
margin: 0px auto; /*中央寄せ*/
padding: 10px;
}
/*あみだくじデータの設定領域の入力項目*/
.kuji-items > input {
height: 30px; /*高さ*/
}
/*くじを作るボタン*/
.create_btn {
font-weight: bold; /*太文字*/
padding: 0.25em 0.5em; /*文字余白*/
text-decoration: none; /*文字装飾なし*/
color: #FFF; /*文字色*/
background: #008080; /*背景色*/
margin-left: 10px; /*左側余白*/
height: 30px; /*高さ*/
}
/*くじコンテナ*/
.kuji-container {
height: 100px; /*高さ*/
background-color: #CBFFD3; /*背景色*/
}
「Views\Shared\_Layout.cshtml」の<head>内にcssへのリンクを追加します。
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Amidakuji</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
<!-- kuji.cssを追加 -->
<link rel="stylesheet" href="~/css/kuji.css" />
</head>
cssにUIを定義する
試行錯誤の結果、あみだ部分はグリッドレイアウトを利用することにしました。
kuji.cssに以下を追加します。内容はコードにコメントで書きました。
・・・省略・・・
/*タイトル*/
.kuji-container > h1 {
color: #000000; /*文字色*/
background: #E6FFE9; /*背景色*/
border-bottom: solid 3px #0000FF; /*下線*/
}
/*説明文*/
.kuji-container > p {
color: #000000; /*文字色*/
border-bottom: solid 3px #0000FF; /*下線*/
}
/*あみだくじの領域*/
.kuji-line {
display: grid; /*グリッドレイアウトにする*/
grid-auto-columns: minmax(10px, auto); /*1列あたりの幅 10px以上*/
grid-auto-rows: minmax(25px, auto); /*1行あたりの高さ 25px以上*/
background-color: #99CCCC; /*背景色*/
position: relative; /*後述の「あみだを隠すためのマスク領域」の基準点とするためにrelativeを指定*/
}
/*あたり・はずれ等の結果*/
.kuji-line > div {
margin: 0px auto; /*中央寄せ*/
}
/*縦線*/
.vertical-line {
background-color: #000000; /*背景色*/
width: 1px; /*幅*/
height: auto; /*高さ*/
margin: 0px auto; /*中央寄せ*/
}
/*横線*/
.horizontal-line {
background-color: #000000; /*背景色*/
width: 100%; /*幅*/
height: 1px; /*高さ*/
margin-left: 50%; /*左マージン 縦線を中央寄せしているため、幅50%分をずらして縦線の位置から始める*/
}
/*くじを辿る時の縦線*/
.vertical-line.follow {
background-color: #FF0000; /*背景色*/
width: 3px; /*幅*/
}
/*くじを辿る時の横線*/
.horizontal-line.follow {
background-color: #FF0000; /*背景色*/
height: 3px; /*幅*/
}
/*選択肢ボタン*/
.select-btn {
color: #0000FF; /*文字色*/
width: 25px; /*幅*/
height: 25px; /*高さ*/
border-radius: 50%; /*角丸 50%で円になる*/
border: solid 2px #0000FF; /*枠線*/
text-align: center; /*文字の中央寄せ*/
margin: 0px auto; /*中央寄せ*/
}
/*選択肢ボタンのマウスオーバー時*/
.select-btn:hover {
background-color: #6495ED; /*背景色*/
}
/*選択したボタン*/
.select-btn.selected {
color: #FF0000; /*文字色*/
border: solid 2px #FF0000; /*枠線*/
background-color: #FFDDFF; /*背景色*/
}
/*あみだを隠すためのマスク領域*/
.mask {
position: absolute; /*「あみだくじの領域」を基準点とするためにabsoluteを指定*/
width: 90%; /*幅 「あみだくじの領域」の90%の幅*/
height: 76%; /*高さ 「あみだくじの領域」の76%の高さ*/
top: 12%; /*上位置 「あみだくじの領域」の上から12%の位置*/
left: 5%; /*左位置 「あみだくじの領域」の左から5%の位置*/
text-align: center; /*文字の中央寄せ*/
border: solid 2px #808080; /*枠線*/
background-color: #E6FFE9; /*背景色*/
background-image: radial-gradient(#808080 10%, transparent 20%), radial-gradient(#808080 10%, transparent 20%); /*背景画像*/
background-size: 10px 10px; /*背景画像のサイズ(幅 高さ)*/
}
「あみだを隠すためのマスク領域」についての説明を補足します。
背景画像に円形グラデーションを指定し、background-sizeで幅、高さを10pxに揃えることで円を描いています。
この円が、マスク領域のサイズ分繰り返されます。
定義したcssを使ってビューをあみだくじっぽくする
Kuji\Index.cshtmlを以下のように変更します。
くじの数は5本固定で、マスク領域を隠したり表示したりする機能はありません。
このあたりは、次回Razorの学習で改善していくつもりです。
@model Amidakuji.Models.KujiModel
@{
ViewData["Title"] = "あみだくじ";
}
<div class="kuji-container">
<h1>@Model.Title</h1>
<p>くじの数は、@Model.NumberOfKuji 本です。</p>
<!--あみだくじの領域(グリッドレイアウト)-->
<div class="kuji-line">
<!--選択肢ボタン-->
<a href="#" class="select-btn" style="grid-row:2;grid-column:1">1</a>
<a href="#" class="select-btn" style="grid-row:2;grid-column:2">2</a>
<a href="#" class="select-btn" style="grid-row:2;grid-column:3">3</a>
<a href="#" class="select-btn" style="grid-row:2;grid-column:4">4</a>
<a href="#" class="select-btn" style="grid-row:2;grid-column:5">5</a>
<!--縦線-->
<div class="vertical-line" style="grid-row:3 / span 15;grid-column:1"></div>
<div class="vertical-line" style="grid-row:3 / span 15;grid-column:2"></div>
<div class="vertical-line" style="grid-row:3 / span 15;grid-column:3"></div>
<div class="vertical-line" style="grid-row:3 / span 15;grid-column:4"></div>
<div class="vertical-line" style="grid-row:3 / span 15;grid-column:5"></div>
<!--横線-->
<p class="horizontal-line" style="grid-row:4;grid-column:1"></p>
<p class="horizontal-line" style="grid-row:10;grid-column:1"></p>
<p class="horizontal-line" style="grid-row:13;grid-column:1"></p>
<p class="horizontal-line" style="grid-row:8;grid-column:2"></p>
<p class="horizontal-line" style="grid-row:12;grid-column:2"></p>
<p class="horizontal-line" style="grid-row:14;grid-column:2"></p>
<p class="horizontal-line" style="grid-row:6;grid-column:3"></p>
<p class="horizontal-line" style="grid-row:13;grid-column:3"></p>
<p class="horizontal-line" style="grid-row:5;grid-column:4"></p>
<p class="horizontal-line" style="grid-row:9;grid-column:4"></p>
<p class="horizontal-line" style="grid-row:15;grid-column:4"></p>
<!--結果-->
<!--横幅を揃えるため、PadRightで5文字分に揃える-->
<div style="grid-row:18;grid-column:1">@Model.Result[0].Item.PadRight(5, ' ')</div>
<div style="grid-row:18;grid-column:2">@Model.Result[1].Item.PadRight(5, ' ')</div>
<div style="grid-row:18;grid-column:3">@Model.Result[2].Item.PadRight(5, ' ')</div>
<div style="grid-row:18;grid-column:4">@Model.Result[3].Item.PadRight(5, ' ')</div>
<div style="grid-row:18;grid-column:5">@Model.Result[4].Item.PadRight(5, ' ')</div>
<!--1行分を余白とする-->
<div style="grid-row:19;grid-column:1 / span 5"></div>
<!--あみだを隠すためのマスク領域-->
<div class="mask"></div>
</div>
</div>
「grid-row:2;grid-column:1」という書き方をしている箇所があります。
これは、グリッドレイアウトの中で、2行目の1列目、という意味です。
「grid-column:1 / span 5」等となっている箇所は、1列目から始めて5列分の領域という意味です。
Excelのセル結合を思い浮かべると分かりやすいかもしれません。
実行してみる
まとめ
今回は、cssを使ってビューのレイアウトを作成しました。
次回は、Razorを使ってマスク領域を隠したり表示したりする機能を作ります。
次回分はこちら⇒ASP.NET Core MVCであみだくじを作ってみる 5 (Razorを使う)