【从实作学习ASP.NET Core】Day12 | 後台 | 资料筛选与分页

前面我们已经完成了 Create 和 Details , 今天就来实作 List 页面


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 (一)

>>:  [Day-15] for回圈

Day 1 Odoo是什麽呢? 云端ERP?

为什麽要使用云端服务? 《2020亚太地区中小企业数位化成熟度研究》报告指出,亚太区近70%的中小企...

Day18

传值与传址,但C++是一个特别的语言比C语言更复杂真要细分可分成3类(传值,传址,传参考),同时指标...

中阶魔法 - 闭包 Closure (一)

前情提要 「艾草艾草,你在做什麽?」 艾草:「没特别做什麽呀!」 「艾草艾草,我问你喔!」 艾草:「...

JS 样板字面值 DAY75

这里先提供一篇 我之前介绍 样板字面值 的基础介绍 https://ithelp.ithome.co...

Javascript 传值传址&深浅拷贝

前言 因为公司前端资料已经处理成单层结构,所以都没注意到浅拷贝、深拷贝的实际差别。 在读完高手文章後...