前面我们已经完成了 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>
看一下成果
<<: [13th-铁人赛]Day 11:Modern CSS 超详细新手攻略 - Position (一)
为什麽要使用云端服务? 《2020亚太地区中小企业数位化成熟度研究》报告指出,亚太区近70%的中小企...
传值与传址,但C++是一个特别的语言比C语言更复杂真要细分可分成3类(传值,传址,传参考),同时指标...
前情提要 「艾草艾草,你在做什麽?」 艾草:「没特别做什麽呀!」 「艾草艾草,我问你喔!」 艾草:「...
这里先提供一篇 我之前介绍 样板字面值 的基础介绍 https://ithelp.ithome.co...
前言 因为公司前端资料已经处理成单层结构,所以都没注意到浅拷贝、深拷贝的实际差别。 在读完高手文章後...