前面我們已經完成了 Create 和 Details , 今天就來實作 List 頁面
前端頁面我們隨便挑幾項出來排版,讓庫存大於 0 的商品顯示在庫:
<td>
@if (item.Stock > 0)
{
@Html.Raw("<span class=" + "\" badge bg-success text-white \"" + ">在庫中</span>")
}
else
{
@Html.Raw("<span class=" + "\" badge bg-warning text-dark \"" + ">缺貨中</span>")
}
</td>
還記得如何從網址傳數值給 Controller 嗎,就是在網址後面加上?
來添加參數
忘記的可以回去看看前面的文章:Day03 | Controller 控制器
所以我們調整Index()
的參數,讓它能用 searchString
的值來搜尋資料庫
public async Task<IActionResult> Index(string searchString)
{
var result = from m in _context.Product select m;
if (!string.IsNullOrEmpty(searchString))
{
result = result.Where(s => s.Name.Contains(searchString));
}
return View(result.Include(p => p.Category).ToListAsync());
}
測試一下,在網址後面傳值?searchString=Nintendo
,果然選出我們要的資料
但是在實務上不可能讓使用者每次搜尋都要改網址,這樣太不直觀了
所以還需要建一個input欄位來讀取searchString
,在前端Index.cshtml
加上input欄位
<form asp-action="Index" class="col-4 ">
<div class="input-group input-group-sm ">
<input class="form-control" type="text" placeholder="Name" name="searchString" />
<input class="btn btn-sm btn-primary" type="submit" value="Search" />
</div>
</form>
要達成分頁,可以建立一個 PaginatedList 來繼承一般 List
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace OnlineShopCMS.Models
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
this.AddRange(items);
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex < TotalPages);
}
}
public static async Task<PaginatedList<T>> CreateAsync(
IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items =
await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
}
}
接著調整 Index()
成下面這個樣子
public async Task<IActionResult> Index(string searchString, string currentFilter, int? pageNumber)
{
if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}
ViewData["CurrentFilter"] = searchString; // 儲存當前搜尋狀態
var result = from m in _context.Product select m;
if (!string.IsNullOrEmpty(searchString))
{
result = result.Where(s => s.Name.Contains(searchString));
}
int pageSize = 5; //一頁顯示幾項
return View(await PaginatedList<Product>.CreateAsync(
result.Include(p => p.Category).AsNoTracking(), pageNumber ?? 1, pageSize)
);
}
最後在前端 Index.cshtml
加上上下頁的按鈕
@{
var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.HasNextPage ? "disabled" : "";
}
<div class="d-flex justify-content-center">
<a asp-action="Index"
asp-route-pageNumber="@(Model.PageIndex - 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @prevDisabled">Previous
</a>
<a asp-action="Index"
asp-route-pageNumber="@(Model.PageIndex + 1)"
asp-route-currentFilter="@ViewData["CurrentFilter"]"
class="btn btn-default @nextDisabled">Next
</a>
</div>
看一下成果