这一篇满满的干货,基于真实SQL 2016数据库,实现bootstrapBlazor中table组件的分页和表外查询,table组件自带查询按钮和模版,但是总感觉没有外部自己实现的来的可控性强,需要先关注的问题如下。
需关注和了解的问题
- ef core下不确定多个查询条件下的查询,就是相对应的文本框中有内容就查,没内容就跳过
- ef core中三目运算符的使用,这是实现无内容时跳过的关键
- 外部按钮的查询事件怎么更新数据至Table组件中,也就是手动更新
@ref的使用,这是更新数据至table组件中的关键,决定了你在外部如何重用table组件
感谢这两位大神的贴子,我也是卡在这里好久没有解决
参考:https://www.cnblogs.com/ysmc/p/16128206.html
参考:https://blog.csdn.net/weixin_42511607/article/details/122283265
完整UI代码
在UI中注释掉了table组件中的搜索模板,并禁止显示搜索按钮,需要特别注意不要给Items绑定数据,否则查询后无法显示,在错误信息中会看到冲突。
OnQueryAsync事件一定要有,不能因为禁止显示按索按钮,就把查询事件也给不要了,查询事件在网页初始化时就会执行,同样外部按钮点击查询时也是调用的这个事件。
@ref="Table",同样非常重要,其中的Table不是组件名称,而是在C#代码中定义的private Table<Book>? Table { get; set; }
@page "/Demo5"
@using Blazor.OnlyServer1.Models;
<div style="height:10%">
<GroupBox Title="搜索条件">
<div class="row g-3 form-inline">
<div class="col-auto col-form-label">
<span>名称</span>
</div>
<div class="col-12 col-sm-2">
<BootstrapInput @bind-Value="@name" PlaceHolder="搜索的名称" maxlength="50" ShowLabel="false" />
</div>
<div class="col-auto col-form-label">
<span>规格</span>
</div>
<div class="col-12 col-sm-2">
<BootstrapInput @bind-Value="@lx" PlaceHolder="请输入规格" maxlength="50" ShowLabel="false" />
</div>
<div class=" btn-group col-12 col-sm-2">
<Button Text="搜索" OnClick="QueryBtn" Color="Color.Success" Icon="fas fa-arrows-rotate"></Button>
<Button Text="重置" OnClick="ResetBtn" Color="Color.Warning" Icon="fas fa-eraser"></Button>
</div>
</div>
</GroupBox>
</div>
<div style="height:90%">
<Table TItem="Book" PageItemsSource="PageItemsSource" IsFixedHeader="true" ShowSearch="false" ShowEmpty="true" SearchMode="SearchMode.Top" ShowSearchButton="false"
IsPagination="true" AllowResizing="true" AutoGenerateColumns="true" ShowColumnList="true" EmptyText="亲,没有查询到需要的数据!" @ref="Table"
IsStriped="true" IsBordered="true" OnResetSearchAsync="@OnResetSearchAsync"
ShowToolbar="true" IsMultipleSelect="true" ShowExtendButtons="false"
OnQueryAsync="@OnSerchAsync">
@* <SearchTemplate>
<GroupBox Title="搜索条件">
<div class="row g-3 form-inline">
<div class="col-auto col-form-label">
<span>名称</span>
</div>
<div class="col-12 col-sm-2">
<BootstrapInput @bind-Value="@name" PlaceHolder="搜索的名称" maxlength="50" ShowLabel="false" />
</div>
<div class="col-auto col-form-label">
<span>规格</span>
</div>
<div class="col-12 col-sm-2">
<BootstrapInput @bind-Value="@lx" PlaceHolder="请输入规格" maxlength="50" ShowLabel="false" />
</div>
</div>
</GroupBox>
</SearchTemplate> *@
</Table>
</div>
上面的代码中已经注释掉了Table组件自带的搜索模版,改为在Table组件外实现,记得进行双向数据绑定。
C#代码
代码中有一些没用的同样注释掉了,还有些事件用不到,如OnQueryAsync、OnResetSearchAsync,其实外部查询按钮就是在填好查询条件(不填写也能查询,在OnSerchAsync中进行处理就行了)后直接调用Table的查询,重置按钮就是把查询的条件清空,然后再调味用Table的查询
using Blazor.OnlyServer1.Models;
using BootstrapBlazor.Components;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using static System.Reflection.Metadata.BlobBuilder;
namespace Blazor.OnlyServer1.Components.Pages
{
public partial class Demo5
{
//重要,用于绑定table组件和在外部访问table组件时使用到
private Table<Book>? Table { get; set; }
//分页的大小
private static IEnumerable<int> PageItemsSource => new int[] { 2, 3 };
private Book SearchModel { get; set; } = new Book();
private List<Book> Books { get; set; }
private string name;
private string lx;
private int TotalCount = 0;
protected override void OnInitialized()
{
base.OnInitialized();
}
//Table外查询按钮事件
private async Task QueryBtn()
{
await Table.QueryAsync(); //调用table的查询事件
}
//Table外重置按钮事件
private async Task ResetBtn()
{
name = "";
lx = "";
await Table.QueryAsync(); //调用table的查询事件
}
//基于数据库的分页查询
private Task<QueryData<Book>> OnQueryAsync(QueryPageOptions options)
{
int TotalCount = 0;
List<Book> books = new List<Book>();
int skip = (options.PageIndex - 1) * options.PageItems;
using (var context =new BookContext())
{
books = context.Books.Skip(skip).Take(options.PageItems).ToList();
TotalCount = context.Books.Count();
}
return Task.FromResult(new QueryData<Book>()
{
Items = books,
TotalCount = TotalCount,
});
}
//点击搜索按钮时的查询,基于数据库分页
private Task<QueryData<Book>> OnSerchAsync(QueryPageOptions options)
{
int skip = (options.PageIndex - 1) * options.PageItems;
//无数据时、无查询条件时显示全部的数据,并进行数据库分页
if (Books == null || Books.Count() == 0||(string.IsNullOrEmpty(name) && string.IsNullOrEmpty(lx)))
{
using (var context = new BookContext())
{
Books = context.Books.Skip(skip).Take(options.PageItems).ToList();
TotalCount = context.Books.Count();
}
}
//处理高级搜索文本
//if (!string.IsNullOrEmpty(options.SearchText))
//{
// name = "";
// lx = "";
// using (var context = new BookContext())
// {
// Books = context.Books.Where(d => d.名称.Contains(options.SearchText) || d.规格.Contains(options.SearchText)).OrderByDescending(d => d.Id).Skip(skip).Take(options.PageItems).ToList();
// TotalCount = context.Books.Where(d => d.名称.Contains(options.SearchText) || d.规格.Contains(options.SearchText)).Count();
// }
//}
//查询条件有一个不为空时使用多个where加三目运算符来实现不确定查询条件有几个时的查询
//查询条件的内容为空时设置true直接跳过
if (!string.IsNullOrEmpty(name)||!string.IsNullOrEmpty(lx))
{
options.SearchText = "";
using (var context = new BookContext())
{
//查询符合条件的数据,并进行分页
Books=context.Books
.Where(d =>string.IsNullOrEmpty(name)?true:d.名称.Contains(name))
.Where(d=>string.IsNullOrEmpty(lx)?true:d.规格.Contains(lx))
.Skip(skip).Take(options.PageItems).ToList();
//查询符合条件的数量,用于实现分页和显示数据量
TotalCount = context.Books
.Where(d => string.IsNullOrEmpty(name) ? true : d.名称.Contains(name))
.Where(d => string.IsNullOrEmpty(lx) ? true : d.规格.Contains(lx))
.Count();
}
}
//处理自定义搜索的文本
return Task.FromResult(new QueryData<Book>()
{
Items = Books,
TotalCount = TotalCount,
});
}
//重置搜索,Table内置
private static Task OnResetSearchAsync(Book item)
{
return Task.CompletedTask;
}
}
}
好了,到此为止查询就基本上搞定了,想实现多字段查询就继续增加查询条件就可以了,也不用像原生SQL一样在那拼接条件字符串,经过这么些天的努力,感觉它终于像个能使用的东西了。