Blazor 自定义可重用基础组件之 带标头排序的Table

news2024/11/27 18:01:01

实现点击标头按所在列值进行排序,是一个非常有用的功能,其他的UI一般搞得非常复杂,添加标志图标什么的,使得本就不宽裕的表格更加拥挤。我的思路是,点击所在列的标头部位,传递标头值,然后根据标头值来改变查询语句。因为并不是所有列都需要排序,需要有一个特征字符。

以下是Table.razor

@typeparam T
<style>
    th {
        text-align: center;
        font-weight: 500;
        font-size: 16px;
        white-space: nowrap;
    }

    td {
        font-size: 14.66px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        line-height: 25px;
    }
</style>
<div>
    @ToolBarContent
</div>
<div>
    <table class="table table-bordered table-hover table-sm table-striped">
        <thead>
            <tr >
                @foreach (var item in HeaderTitles)
                {
                    if (IsSortabledColonum((string)item))
                    {
                        <th @onclick="()=>HeaderClick((string)item)" style="color:blue;cursor:pointer;">@HeaderTitle((string)item)</th>
                    }
                    else
                    {
                        <th>@item</th>
                    }
                }
            </tr>
        </thead>
        <tbody>
            @if (PageData.HasData)
            {
                foreach (var item in PageData)
                {
                    <tr @onclick="()=>RowClick(item)" >
                        @RowContent(item)
                    </tr>
                }
            }
            else
            {
                <tr>
                    <td colspan="@columnsCount" class="text-center">暂无数据</td>
                </tr>
            }
        </tbody>
    </table>
    <div class="row col-12 justify-content-end">
        <p style="width:auto;">
            <label class="form-label">
                设置行数:
                <select class="form-control-sm mt-0" @onchange="PageSizeChanged">
                    <option value="10">10</option>
                    <option value="15" selected>15</option>
                    <option value="20">20</option>
                    <option value="25">25</option>
                    <option value="30">30</option>
                </select>
            </label>
        </p>

        <button class="btn btn-primary btn-sm" disabled="@PageData.NoPreviousPage" @onclick="()=>GotoPage(1)" style="width:80px;height:30px;">首页</button>
        <button class="btn btn-primary btn-sm" disabled="@PageData.NoPreviousPage" @onclick="PreviousPage" style="width:80px;height:30px;">上一页</button>
        <button class="btn btn-primary btn-sm" disabled="@PageData.NoNextPage" @onclick="NextPage" style="width:80px;height:30px;">下一页</button>
        <button class="btn btn-primary btn-sm" disabled="@PageData.NoNextPage" @onclick="()=>GotoPage(PageData.TotalPages)" style="width:60px;height:30px;">尾页</button>
        <input type="number" style="width:60px;height:30px;" @bind-value="pageNum" />
        <button class="btn btn-primary btn-sm" disabled="@PageData.NoGoto" @onclick="()=>GotoPage(pageNum)" style="width:60px;height:30px;">跳转</button>
        <p class="mx-4" style="width:130px;height:30px;">总页数:@PageData.TotalPages</p>
        <p style="width:130px;height:30px;">当前页:@pageIndex</p>
        <p style="width:130px;height:30px;">总条数:@PageData.ItemCount</p>
    </div>
</div>

Table.razor.cs

    public partial class Table<T> : ComponentBase, IDisposable where T : class
    {
        private int pageIndex = 1;
        private int pageSize = 15;
        private int pageNum;
        private IQueryable<T>? query;
        private int columnsCount;//设定列数

        private PaginatedList<T> PageData { get; set; } = new(new List<T>(), 0, 1, 1);

        [Parameter]
        public RenderFragment? ToolBarContent { get; set; }
        [Parameter]
        public required Array HeaderTitles { get; set; }
        [Parameter]
        public required RenderFragment<T> RowContent { get; set; }
        [Parameter]
        public RenderFragment<RenderFragment>? RowTemplate { get; set; }
        [Parameter]
        public EventCallback<T> OnRowClick { get; set; }
        [Parameter]
        public EventCallback<string> OnHeaderClick { get; set; }
        public async void RowClick(T item)
        {
            if (OnRowClick.HasDelegate)
                await OnRowClick.InvokeAsync(item);
        }
        public async void HeaderClick(string title)
        {
            if (OnHeaderClick.HasDelegate)
                await OnHeaderClick.InvokeAsync(title[..^1]);
        }
        protected override void OnParametersSet()
        {
            base.OnParametersSet();
            columnsCount = HeaderTitles.Length;
        }
        public int PageSize
        {
            get => pageSize;

            set
            {
                if (value != pageSize)
                {
                    pageSize = value;
                    OnChange();
                }
            }
        }

        public IQueryable<T> Query
        {
            get => query ?? (new List<T>()).AsQueryable();
            set
            {
                if (value != query)
                {
                    query = value;
                    OnChange();
                }
            }
        }
        private void OnChange()
        {
            PageData = PaginatedList<T>.Create(Query, pageIndex, PageSize);
            StateHasChanged();
        }
        private void PreviousPage()
        {
            pageIndex--;
            OnChange();
        }
        private void NextPage()
        {
            pageIndex++;
            OnChange();
        }
        private void GotoPage(int pageNum)
        {
            if (pageNum > 0 && pageNum != pageIndex && pageNum <= PageData.TotalPages)
            {
                pageIndex = pageNum;
                OnChange();
            }
        }
        private void PageSizeChanged(ChangeEventArgs e)
        {
            if (e.Value != null)
            {
                PageSize = int.Parse((string)e.Value);
            }
        }
        private string HeaderTitle(string title)
        {
            if (title.EndsWith('|'))
            {
                return title[..^1];
            }
            return title;
        }
        private bool IsSortabledColonum(string title)
        {
            return title.EndsWith('|'); //点击标头可以排序等操作。
        }

        protected virtual void Dispose(bool disposing)
        {
        }

        void IDisposable.Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }

还是那个天气表格:

@page "/fetchdata"
@using MySoft.Data
@inject WeatherForecastService ForecastService

<PageTitle>Weather forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from a service.</p>

<Table @ref="myTable" HeaderTitles="headerTitles" T="WeatherForecast" OnHeaderClick="OnSort">
    <RowContent>
        <td>@context.Date.ToShortDateString()</td>
        <td>@context.TemperatureC</td>
        <td>@context.TemperatureF</td>
        <td>@context.Summary</td>
    </RowContent>
</Table>

@code {
    private WeatherForecast[] forecasts = new WeatherForecast[] { };
    private YtTable<WeatherForecast>? myTable;
    private Array headerTitles = new string[]
    {
        "Date|","Temp. (C)","Temp. (F)","Summary|"
    };
    private bool dateSort, summarySort;
    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
    }
    private IQueryable<WeatherForecast> Query
    {
        get
        {
            if (myTable != null)
            {
                return myTable.Query;
            }
            return (new List<WeatherForecast>()).AsQueryable();
        }
        set
        {
            if (myTable != null)
            {
                myTable.Query = value;
            }
        }
    }
    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);
        if (firstRender)
        {
            Query = forecasts.AsQueryable();
        }
    }
    private void OnSort(string title)
    {
        switch (title)
        {
            case "Date":
                sortOnDate();
                break;
            case "Summary":
                sortOnSummary();
                break;
            default:
                break;
        }
    }
    private void sortOnDate()
    {
        dateSort = !dateSort;
        if (dateSort)
        {
            Query = Query.OrderBy(o => o.Date);
        }
        else
        {
            Query = Query.OrderByDescending(o => o.Date);
        }
    }
    private void sortOnSummary()
    {
        summarySort = !summarySort;
        if (summarySort)
        {
            Query = Query.OrderBy(o => o.Summary);
        }
        else
        {
            Query = Query.OrderByDescending(o => o.Summary);
        }
    }
}

效果:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/720101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

裸机搭建k8s报错记录

安装教程参考 修复一、 cd /etc/kubernetes/manifests vim kube-scheduler.yaml注释掉 重启 systemctl restart kubelet.service问题二、 https://github.com/kubernetes/kubernetes/issues/70202 一直处于创建中状态 网络原因 cat << EOF > /run/flannel/subnet.…

golang 结构体struct转map实践

1、反射 type sign struct { Name string json:"name,omitempty" Age int json:"age,omitempty" } var s sign s.Name "csdn" s.Age 18 //方式1 反射 var data make(map[string]interface{}) t : reflect.TypeOf(s) v : …

第五步:STM32F4端口复用

什么是端口复用&#xff1f; STM32有很多的内置外设&#xff0c;这些外设的外部引脚都是与GPIO复用的。也就是说&#xff0c;一个GPIO如果可以复用为内置外设的功能引脚&#xff0c;那么当这个GPIO作为内置外设使用的时候&#xff0c;就叫做复用。 例如串口 1 的发送接收引脚…

【C++11】移动语义,完美转发

1.移动语义 1.为什么要有移动语义&#xff1f; C中有拷贝构造函数和拷贝复制运算符&#xff0c;但是这需要占用一定的空间 class MyClass { public:MyClass(const std::string& s): str{ s }{};MyClass(const MyClass& m){strm.str;}private:std::string str; };int …

NSS [NSSRound#7 Team]ec_RCE

NSS [NSSRound#7 Team]ec_RCE 源码如下&#xff1a; <?PHPif(!isset($_POST["action"]) && !isset($_POST["data"]))show_source(__FILE__);putenv(LANGzh_TW.utf8); $action $_POST["action"];$data "".$_POST["…

代理IP,如何助力大数据时代

代理IP&#xff0c;如何为大数据助力 华科云商助力大数据 近年来&#xff0c;我国互联网商业保持持续发展的状态。大环境的优化&#xff0c;各项相关政策的出台&#xff0c;也为互联网经济的发展&#xff0c;提供了强有力的支持。大大小小的企业都想乘风起势&#xff0c;大展宏…

Django核心

安装django pip install django # pip install django3.1.6创建django项目 在一个项目中可以包含多个应用程序。 django-admin startapp app_name #创建一个应用程序 django-admin startproject project_name #创建一个项目运行django项目 python manage.py runserver 80…

REST风格讲解

1.REST风格简介 优点&#xff1a;隐藏资源访问的行为&#xff0c;无法通过地址得知对资源的操作&#xff0c;并且简化了书写 rest风格大概将请求方式分成了Get Post Put Delete四种操作方法。上述行为是约定的方式并不是规范。 RequestMapping注解里面value值存储访问的路…

Docker 中的 .NET 异常了怎么抓 Dump (转载)

一、背景 1. 讲故事 有很多朋友跟我说&#xff0c;在 Windows 上看过你文章知道了怎么抓 Crash, CPU爆高&#xff0c;内存暴涨 等各种Dump&#xff0c;为什么你没有写在 Docker 中如何抓的相关文章呢&#xff1f;瞧不上吗&#xff1f; 哈哈&#xff0c;在DUMP的分析旅程中&a…

【前端学JAVA】基础语法

作为一个前端程序员&#xff0c;其发展前途是远不及后端程序员的。因此&#xff0c;只有了解后端&#xff0c;才能让自己更加具备核心竞争力。本系列教程将以一个前端程序员的角度快速学习JAVA。 新建项目 开发JAVA程序&#xff0c;我们第一步是使用IDEA新建一个项目&#xf…

紫光展锐携手中国联通共建数字世界

6月28日&#xff0c;2023上海世界移动大会&#xff08;MWC上海&#xff09;首日&#xff0c;联通华盛总经理李立新、联通华盛副总经理陈丰伟一行莅临紫光展锐展台参观&#xff0c;紫光集团高级副总裁、紫光展锐CEO任奇伟博士&#xff0c;紫光展锐执行副总裁、工业电子事业部总经…

如何提高OAK相机在树莓派和JETSON上的运行帧率?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手君。 最…

Lim接口测试平台-接口测试功能详解

一、接口测试 项目地址&#xff1a;Gitee/Github 接口测试模块是整个Lim平台的核心&#xff0c;左侧是接口的模块树&#xff0c;右侧顶部是用例操作功能区&#xff0c;列表展示接口用例信息&#xff1a; 文章目录 一、接口测试 二、维护接口用例 各步骤类型详解 1&#x…

picard的安装

最近在通过GATK所介绍的best practice流程来call SNP流程 1.流程 1.1 BWA比对&#xff0c;获得sam文件 1.2 准备用picard来压缩排序sam文件为bam文件&#xff0c;并对bam文件进行去重复&#xff08;duplicates marking&#xff09; 这是就需要用到picard软件 按照教程网页上…

Mac使用Puppeteer,并启动chromium

Mac使用Puppeteer&#xff0c;并启动chromium Puppeteer官网 chromium下载地址 通过chrome://version 可查询 Chromium 浏览器信息 const puppeteer require(puppeteer);(async () > {const browser await puppeteer.launch({executablePath: 上图可执行文件路径,headl…

爬取12306上所有城市的站台信息

0. 需求 爬取所有城市下的站台信息保存到Excel中: 效果: 1. 定位数据源 在12306随便一个车票查询页面上,通过F12控制台获取网站请求车站数据的URL 博主当前获取的URL为: https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version1.9270*注意…

服务器数据恢复-raid10重建为raid6的数据恢复案例

服务器故障&#xff1a; 一台IBM V7000存储中的vdisk丢失&#xff0c;Solaris操作系统中的部署的Oracle数据库不可用。经过和工作人员的沟通得知故障原因&#xff1a;工作人员进行重建MDisk的操作&#xff0c;将原先的raid10重建为raid6&#xff0c;然后又再次重建为raid10&…

RLHF文本生成图模型

背景 语言大模型有RLHF技术点&#xff0c;是否图生成也需要RLHF。要回答这个问题其实首先需要回答的问题有三个&#xff1a; 1.RLHF到底是个什么技术 2.为什么需要用RLHF技术&#xff0c;在语言大模型用RLHF模型解决什么问题点 3.图在什么情况下需要用到RLHF技术点 RLHF技…

如何实现监听某些数值,异步页面请求后再渲染到页面上

问题&#xff1a; 当我们遇到小程序在某个页面&#xff0c;需要刷新另一个页面的数据时&#xff0c;通常都是返回到刷新页面&#xff0c;然后执行onshow的函数。 但是是否可以拿数值之后&#xff0c;直接就更新相应的数值就行了&#xff1f;不用整体刷新。或者有时候页面已经…

7.3.4 【Linux】文件系统检验

xfs_repair 处理 XFS 文件系统 xfs_repair 可以检查/修复文件系统&#xff0c;不过&#xff0c;因为修复文件系统是个很庞大的任务&#xff01;因此&#xff0c;修复时该文件系统不能被挂载。 fsck.ext4 处理 EXT4 文件系统 fsck 是个综合指令&#xff0c;如果是针对 ext4 的…