使用 EF 和 Web API 实现 ASP.NET Core Blazor 主从表格(含筛选和排序)





5.00/5 (4投票s)
本文将介绍如何使用 Entity Framework 和 Web API,使用 ASP.NET Core Blazor 创建自定义的主从 HTML 表格,并实现排序和筛选功能。我们还将利用 Blazor 的动态内容功能来创建主从表。
引言
* 欢迎观看我的 YouTube 视频教程,学习 使用 Entity Framework 和 Web API 实现 ASP.NET Core Blazor 主从表。
本文将介绍如何使用 Entity Framework 和 Web API,使用 ASP.NET Core Blazor 创建自定义的主从 HTML 表格,并实现排序和筛选功能。我们还将利用 Blazor 的动态内容功能来创建主从表。
请阅读我之前的文章,深入了解 ASP.NET Core Blazor 入门。
- 使用 Entity Framework 和 Web API 实现 ASP.NET Core Blazor CRUD
- 使用 Entity Framework 和 Web API 实现 ASP.NET Core Blazor 筛选和排序
本文将讲解
- 创建示例数据库和 SQL Server 中的 `Student` 主表和明细表,用于在我们的 Web 应用程序中显示
- 如何创建 ASP.NET Core Blazor Web 应用程序
- 如何安装 Entity Framework 所需的包并创建 `DBContext` 类
- 如何从 Web API 获取结果并绑定到 Blazor 客户端的 Razor 视图
- 创建具有排序和筛选功能的主/从 HTML 表格
- 使用 Blazor 动态内容创建主/从表格
Blazor 动态内容
在 Blazor 中,我们可以使用 C# 代码编写自己的组件。我们都知道,在 Blazor 中,我们可以在客户端 HTML 函数部分编写 C# 代码。有时,我们需要动态地创建并将结果绑定到 HTML 页面。在本文中,我们将使用 Blazor 动态内容,在运行时动态创建明细表,并在用户单击主表中的明细显示图标时进行显示。
我们也可以称之为:主/从 HTML 表格、分层表格或嵌套表格。
为什么需要嵌套表格、分层表格或主/从表格?
在实际项目中,例如订单管理、生产管理、学生管理等,我们需要以分层结构显示数据。
例如,我们以大学的 `Students` 管理项目为例。对于 `students` 管理,我们需要创建许多关联表,例如 `Student Master`(学生主表)和 `Student Details`(学生明细表)等。在 `Student Master` 中,我们存储 `student ID`、`Name`(姓名)、`Email`(电子邮件)、`Phone`(电话)和 `Address`(地址)。在 `Student Details` 中,我们存储 `student` 的期末考试成绩,用于显示 `Student Major`(学生专业)、`Studying Year with Term`(学年与学期)和 `Grade details`(成绩详情)。这两个表都将通过 `StudentID` 相关联。我们将这两个表连接起来,以显示完整的学生详细信息。
最初,我们将所有 `students` 的主记录显示在 HTML 表格中供查看。用户可以单击每个 `student` 旁边的展开图标来查看其完整详细信息。
在这里,下图显示了我们将 `Student Master` 和 `Student detail` 的结果都绑定到 HTML 表格中,并且只有当用户单击主表 `StudentID` 旁边的图标时才显示明细。当用户单击 `StudentID` “`2”时,下一个明细 `Grid` 将被显示,以 `Major`(专业)、`Year`(年级)、`Term`(学期)和 `Grade`(成绩)来显示 `student` 的成绩明细。
在这里,我们按每个 `student Id` 显示 `student` 的详细信息。
在我们的示例中,我们还为我们的主/从表格添加了筛选和排序功能。
背景
请确保您的计算机已安装所有先决条件。如果没有,请逐一下载并安装。请注意,由于 Blazor 是一个新框架,我们必须安装 Visual Studio 2017 (15.7) 或更高版本的预览版。
- 安装 .NET Core 2.1 Preview 2 SDK。(您可以在此 链接 找到所有版本)
- 安装 Visual Studio 2017 (15.7) 的最新预览版。
- 安装 ASP.NET Core Blazor Language Services 以获得 Blazor 扩展。
Using the Code
步骤 1 - 创建数据库和表
我们将使用我们的 SQL Server 数据库来为 WEB API 和 EF 做准备。首先,我们创建一个名为 `StudentsDB` 的数据库和一个名为 `StudentMaster` 的表。以下是用于在我们的项目中创建数据库表和插入示例记录的 SQL 脚本。请在您的本地 SQL Server 中运行以下查询,以创建数据库和表。
USE MASTER
GO
--1) Check
-- for the Database Exists.If the database is exist then drop and create new DB
IF EXISTS(SELECT [name] FROM sys.databases WHERE[name] = 'StudentGradeDB')
DROP DATABASE StudentGradeDB
GO
CREATE DATABASE StudentGradeDB
GO
USE StudentGradeDB
GO
--1) //////////// StudentMasters
CREATE TABLE[dbo].[StudentMasters](
[StdID] INT IDENTITY PRIMARY KEY,
[StdName][varchar](100) NOT NULL,
[Email][varchar](100) NOT NULL,
[Phone][varchar](20) NOT NULL,
[Address][varchar](200) NOT NULL
)
--insert sample data to Student Master table
INSERT INTO [StudentMasters]([StdName], [Email], [Phone], [Address])
VALUES('Shanu', <a href="mailto:'syedshanumcain@gmail.com'">'syedshanumcain@gmail.com'</a>,
'01030550007', 'Madurai,India')
INSERT INTO [StudentMasters]([StdName], [Email], [Phone], [Address])
VALUES('Afraz', <a href="mailto:'Afraz@afrazmail.com'">'Afraz@afrazmail.com'</a>,
'01030550006', 'Madurai,India')
INSERT INTO [StudentMasters]([StdName], [Email], [Phone], [Address])
VALUES('Afreen', <a href="mailto:'Afreen@afreenmail.com'">'Afreen@afreenmail.com'</a>,
'01030550005', 'Madurai,India')
select * from[StudentMasters]
--1) //////////// StudentDetails
CREATE TABLE[dbo].[StudentDetails](
[StdDtlID] INT IDENTITY PRIMARY KEY, [StdID] INT,
[Major][varchar](100) NOT NULL,
[Year][varchar](30) NOT NULL,
[Term][varchar](30) NOT NULL,
[Grade][varchar](10) NOT NULL)
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(1, 'Computer Science', 'FirstYear', 'FirstTerm', 'A')
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(1, 'Computer Science', 'FirstYear', 'SecondTerm', 'B')
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(1, 'Computer Science', 'SecondYear', 'FirstTerm', 'C')
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(2, 'Computer Engineer', 'ThirdYear', 'FirstTerm', 'A')
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(2, 'Computer Engineer', 'ThirdYear', 'SecondTerm', 'A')
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(3, 'English', 'First Year', 'FirstTerm', 'C')
INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])
VALUES(3, 'Economics', 'First Year', 'FirstTerm', 'A')
select * from StudentDetails
步骤 2 - 创建 ASP.NET Core Blazor 应用程序
在安装了上述所有先决条件和 ASP.NET Core Blazor Language Services 后,在您的桌面上单击“开始”>>“程序”>>“Visual Studio 2017”>>“Visual Studio 2017”。单击“新建”>>“项目”。选择“Web”>>“ASP.NET Core Angular Web Application”。输入您的项目名称,然后单击“确定”。
选择 Blazor (ASP.NET Core hosted),然后单击“确定”。
创建 ASP.NET Core Blazor 应用程序后,请等待几秒钟。您将在解决方案资源管理器中看到以下结构。
ASP.NET Core Blazor 解决方案有什么新内容?
当我们创建新的 ASP.NET Core Blazor 应用程序时,我们可以看到解决方案资源管理器中会自动创建 3 个项目。
客户端项目
创建的第一个项目是客户端项目,它将命名为 `Solutionname.Client`。在这里,我们可以看到我们的 `Solutionname` 是“`BlazorASPCORE”。项目名为客户端,此项目主要专注于所有客户端视图。在这里,我们将添加所有要在客户端浏览器中显示的页面视图。
我们可以看到已经添加了一些示例页面,并且还有一个共享文件夹,它与我们的 MVC 应用程序中的共享文件夹和布局页面(用于主页面)类似。在 Blazor 中,我们有 `MainLayout`,它将像主页面一样工作,还有 `NavMenu` 用于显示左侧菜单。
服务器项目
顾名思义,此项目将用作服务器项目。此项目主要用于创建所有控制器和 WEB API 控制器,以执行所有业务逻辑并通过 WEB API 执行 CRUD 操作。在我们的演示应用程序中,我们将在服务器项目中添加一个 Web API,并在我们的客户端应用程序中添加所有 WEB API。此服务器项目将用于从数据库获取/设置数据,并且从我们的客户端项目,我们将绑定或将结果发送到此服务器以在数据库中执行 CRUD 操作。
共享项目
顾名思义,此项目充当共享项目。此项目将作为服务器项目和客户端项目的模型。在此共享项目中声明的模型将在服务器项目和客户端项目中使用。我们还在项目所需的此处安装所有包,例如,要使用 Entity Framework,我们将所有包安装在此共享项目中。
运行以测试应用程序
当我们运行应用程序时,我们可以看到左侧是导航,右侧包含数据。我们可以看到 Blazor 网站中显示的默认示例页面和菜单。我们可以使用这些页面,或者删除它们并从我们自己的页面开始。
现在,让我们看看如何添加新页面以执行 CRUD 操作来维护 `student` 详细信息。
使用 Entity Framework
要在我们的 Blazor 应用程序中使用 Entity Framework,我们需要安装以下包。
安装包
转到“工具”,然后选择 ->“NuGet 包管理器” ->“程序包管理器控制台”。
您将在 VS 2017 IDE 的底部看到控制台。在控制台上的组合框的右侧,选择默认项目为您的共享项目“选择共享”。
- 您将看到 PM>,然后复制并粘贴下面的行以安装数据库提供程序包。此包用于将数据库提供程序设置为 SQL Server。
Install-Package Microsoft.EntityFrameworkCore.SqlServer
我们可以看到包已安装在我们的共享文件夹中。
安装 Entity Framework
- 您将看到 PM>,然后复制并粘贴下面的行以安装 EF 包。
Install-Package Microsoft.EntityFrameworkCore.Tools
创建 DB Context 并设置 DB 连接字符串
- 您将看到 PM>,然后复制并粘贴下面的行来设置连接字符串并创建 DB Context。这是重要部分,因为我们提供了 SQL Server 名称、数据库名称以及 SQL server UID 和 SQL Server Password 以连接到我们的数据库以显示我们的主/从表格。我们还提供了我们的两个 SQL 表名称“`StudentMasters, `StudentDetails”来创建我们共享项目中的 `Model` 类。
Scaffold-DbContext "Server= ServerName;Database=StudentGradeDB; user id=UserID;password=Password;Trusted_Connection=True;MultipleActiveResultSets=true" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables StudentMasters,StudentDetails
按 Enter 创建连接字符串、模型类和数据库上下文。
我们将在我们的共享项目中看到 `StudentMasters` 和 `StudentDetails Model` 类以及 `StudentGradeDBContext` 类。我们将在我们的服务器项目中继续使用此 `Model` 和 `DBContext` 来创建 Web API 以执行 CRUD 操作。
为获取学生详细信息创建 Web API
要创建我们的 WEB API 控制器,请右键单击“Controllers”文件夹。单击“添加新控制器”。
在这里,我们将使用 `Scaffold` 方法来创建我们的 WEB API。我们选择“带有操作的 API 控制器,使用 Entity Framework”。
从共享项目中选择我们的 `Model` 和 `DatabaseContext`。
从共享项目中选择我们的 `StudentMasters` 模型。
将数据上下文类选择为共享项目中的 `StudentsDBContext`。如果需要,我们的 `Controller` 名称将自动添加,您可以更改它并单击“添加”。
我们将仅使用 Web API 的 `Get` 方法。
与此类似,我们也为 `StudentDetails` 创建了一个 Web API。
要测试 `Get` 方法,我们可以运行我们的项目并复制 `GET` 方法的 API 路径。在这里,我们可以看到获取 _api/StudentMasters/_ 的 API 路径。
运行程序并粘贴 API 路径以测试我们的输出。
对于 `StudentDetails`,我们可以传递 `Student ID` 来获取单个 `student` 的详细信息。在这里,我们可以看到 `student ID` 为“`1”的结果,我们调用 Web API _/api/StudentDetails/1_。
现在,我们将从我们 `Client` 项目的 Razor 视图页面中绑定所有这些 WEB API 的 Json 结果,以显示主/从 HTML 表格。
处理客户端项目
注意:在本文中,我们将创建 2 个 Razor 页面。在一个 Razor 页面中,我们将创建主从 HTML 表格,并使用常规绑定方法;在另一个 Razor 页面中,我们将使用 Blazor 动态内容绑定明细表。
具有常规绑定的 Razor 页面
首先,我们需要添加新的 Razor 视图页面。
添加 Razor 视图
要添加 Razor 视图页面,请右键单击客户端项目中的 _Pages_ 文件夹。单击“添加”>>“新建项”。
选择 Razor View >> 输入您的页面名称。在这里,我们将其命名为 _Students.chtml_。
在 Razor 视图页面中,代码有 3 部分:首先是导入部分,我们在这里导入所有要在视图中使用的引用和模型;其次是 HTML 设计和数据绑定部分;最后是函数部分,用于调用所有 Web API 以绑定到我们的 HTML 页面,并执行要在视图页面中显示的客户端业务逻辑。
导入部分
首先,我们在 Razor 视图页面中导入所有必需的支持文件和引用。在这里,我们首先导入我们要在视图中使用的 `Model` 类,并导入 `HTTPClient` 以调用 Web API 来执行 CRUD 操作。
@using BLAZORASPCORE.Shared
@using BLAZORASPCORE.Shared.Models
@page "/Students"
@using Microsoft.AspNetCore.Blazor.Browser.Interop
@inject HttpClient Http
主 HTML 表格数据绑定部分
接下来,我们设计 `Student` 页面,将 Web API 返回的 `student Master` 和 `Student Detail` 结果绑定到 HTML 表格。
绑定学生主详细信息
在 `Init` 方法中,我们从 Web API 获取学生主详细信息,并使用 `foreach` 循环将结果绑定到 HTML 表格。在这里,我们绑定 `Student Master` 表格的结果,并在每行的第一个单元格中添加切换图标。在切换图标的单击事件中,我们调用 `getStudentsDetails(studentsID)` 方法来显示相关 `Student` 的 `Detail` HTML 表格。我们将 `Student ID` 传递给函数,获取相关的 `student` 详细信息,并将结果绑定到明细表格。此外,我们只在单击切换图标按钮时显示明细表格,如果再次单击切换按钮,则隐藏明细表格。
@foreach (var StudentMasters in stdMaster)
{
<tr style="border-style:dashed;border-width:2px;
border-color: @(StudentMasters.StdId == studentIDs ? "#ff6a00": "#a2aabe")">
<td align="center" style="border: solid1px#659EC7; padding: 5px;table-layout:fixed;">
@if (@StudentMasters.StdId == studentIDs)
{
<img src="@Imagename" onclick="@(async () =>
await getStudentsDetails(@StudentMasters.StdId))" />
}
else
{
<img src="Images/toggle.png" onclick="@(async () =>
await getStudentsDetails(@StudentMasters.StdId))" />
}
</td>
<td align="center">
<span style="color:#9F000F">
@StudentMasters.StdId
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@StudentMasters.StdName
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@StudentMasters.Email
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@StudentMasters.Phone
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@StudentMasters.Address
</span>
</td>
</tr>
在表头添加排序功能
在这里,我们只为主 HTML 表格添加了排序和筛选功能。如果需要,我们也可以为明细表格实现相同的功能。
在主表格的表头部分,每个表头都添加了排序图标。在排序图标按钮的单击事件中,我们调用排序函数,并将每个排序列名传递给单击事件。在函数代码部分,我们对 Web API 进行排序,并按每个列标题的排序图标单击进行升序和降序显示结果。
<table style="background-color:#FFFFFF; border-style:inset;border-width:1px;
border-color:#6D7B8D; padding:2px;width:100%;table-layout:fixed;" cellpadding="1" cellspacing="1">
<tr style="background-color:#2d364d ; color:#FFFFFF ;border-style:dashed;
border-width:2px;border-color:0A2464;" >
<td width="30" align="center"></td>
<td width="80" align="center">
<img src="@ImageSortname" onclick="@(async () => await StudentSorting("StdId"))"
height="24" width="24"/>
Student ID
</td>
<td width="240" align="center">
<img src="@ImageSortname" onclick="@(async () => await StudentSorting("StdName"))"
height="24" width="24"/>
Student Name
</td>
<td width="240" align="center">
<img src="@ImageSortname" onclick="@(async () => await StudentSorting("Email"))"
height="24" width="24"/>
Email
</td>
<td width="120" align="center">
<img src="@ImageSortname" onclick="@(async () => await StudentSorting("Phone"))"
height="24" width="24"/>
Phone
</td>
<td width="340" align="center">
<img src="@ImageSortname" onclick="@(async () => await StudentSorting("Address"))"
height="24" width="24"/>
Address
</td>
</tr>
在表头添加筛选功能
在表头部分,我们添加了一个新行。在新行中,我们在每个列中添加 `Textbox` 来对绑定的结果进行筛选。在 `Textbox` 的 `onChange` 事件中,我们调用方法来执行代码函数部分的筛选操作。
<tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;">
<td width="30" align="center"></td>
<td width="80" align="center">Filter : </td>
<td width="240" align="center">
<input width="70" <a href="mailto:onchange=@OnstdNameChanged">
onchange=@OnstdNameChanged</a> oninput="(this.dispatchEvent(new CustomEvent
('change', {bubbles: true})))" />
</td>
<td width="240" align="center">
<input width="70" <a href="mailto:onchange=@OnEmailChanged">
onchange=@OnEmailChanged</a> oninput="(this.dispatchEvent(new CustomEvent
('change', {bubbles: true})))" />
</td>
<td width="120" align="center">
<input width="70" <a href="mailto:onchange=@OnPhoneChanged">
onchange=@OnPhoneChanged</a> oninput="(this.dispatchEvent(new CustomEvent
('change', {bubbles: true})))" />
</td>
<td width="340" align="center">
<input width="70" <a href="mailto:onchange=@OnAddressChanged">
onchange=@OnAddressChanged</a> oninput="(this.dispatchEvent(new CustomEvent
('change', {bubbles: true})))" />
</td>
</tr>
绑定明细表格结果
首先,我们检查 `StudentDetails` 结果是否为 `null`。如果不为 `null`,则将结果绑定到 HTML 表格。在绑定结果之前,我们还检查 `showDetailStatus ==1`,这意味着显示或隐藏明细表格。默认情况下,我们将 `showDetailStatus` 设置为 `0`,并在主表格切换图标单击事件中将其更改为 `1`。如果 `showDetailStatus` 为 `1`,则显示明细表格,我们还会检查主表格 `StudentsID` 与学生明细,并将结果绑定到明细表格。
@if (stdDetail != null)
{
@if (showDetailStatus == 1)
{
@if (@StudentMasters.StdId == studentIDs)
{
<tr style="background-color:#6D7B8D ; color:honeydew ;
border-style:dashed;border-width:2px;border-color:#ECF3F4;">
<td colspan="6" align="center">
Student Details of Student Id - <strong>@StudentMasters.StdId </strong>,
Total @stdDetail.Length Grade details for this Student
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
<table style="background-color:#ECF3F4;border-style:dashed;
border-width:2px;border-color:#0A2464; padding:5px;width:100%;
table-layout:fixed;" cellpadding="1" cellspacing="1">
<tr style="background-color:#659EC7 ; color:#FFFFFF ;
border-style:dashed;border-width:2px;border-color:0A2464;">
<td width="160" align="center">
<Strong>Student Detail</Strong>
</td>
<td width="240" align="center">
Major
</td>
<td width="240" align="center">
Year
</td>
<td width="120" align="center">
Term
</td>
<td width="340" align="center">
Grade
</td>
</tr>
@foreach (var stdDtls in stdDetail)
{
<tr>
<td align="center">
@stdDtls.StdDtlId
</td>
<td align="center">
<span style="color:#9F000F">
@stdDtls.Major
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@stdDtls.Year
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@stdDtls.Term
</span>
</td>
<td align="center">
<span style="color:#9F000F">
@stdDtls.Grade
</span>
</td>
</tr>
}
</table>
</td>
</tr>
}
}
}
函数部分
函数部分用于调用所有 Web API 以绑定到我们的 HTML 页面,并执行要在视图页面中显示的客户端业务逻辑。
Init 方法
在 `Init` 方法中,我们获取 `student` 详细信息的 Web API 结果,并将其存储在 `StudentMaster` 对象中。我们使用此对象通过 `foreach` 语句将其绑定到我们的 HTML 表格。
@functions {
StudentMasters[] stdMaster;
StudentDetails[] stdDetail;
StudentMasters stdmst = new StudentMasters();
StudentDetails stdDtl = new StudentDetails();
int showDetailStatus = 0;
int sortStatus = 0;
int studentIDs = 0;
string Imagename = "Images/toggle.png";
string ImageSortname = "Images/sortAsc.png";
protected override async Task OnInitAsync()
{
stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");
}
明细表格绑定、隐藏/显示方法
在主表格切换图标单击事件中,我们调用下面的方法,并将 `studentID` 传递给它,以从 Web API 获取相应的 `student` 详细信息,并将结果绑定到明细表格。
protected async Task getStudentsDetails(int StudID)
{
if (studentIDs != StudID)
{
Imagename = "Images/expand.png";
showDetailStatus = 1;
}
else
{
if (showDetailStatus == 0)
{
Imagename = "Images/expand.png";
showDetailStatus = 1;
}
else
{
Imagename = "Images/toggle.png";
showDetailStatus = 0;
}
}
studentIDs = StudID;
stdDetail = await Http.GetJsonAsync<StudentDetails[]>("/api/StudentDetails/" +
Convert.ToInt32(StudID));
}
排序方法
在每个列标题的排序图像单击时,我们调用此方法并将列名传递给该方法。在此方法中,根据列名,我们对 Web API 结果进行排序,并将结果绑定到 HTML 表格。我们还进行升序和降序的排序。
//Sorting
protected async Task StudentSorting(string SortColumn)
{
stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");
if (ids == 0)
{
ImageSortname = "Images/sortDec.png";
ids = 1;
switch (SortColumn)
{
case "StdId":
stdMaster = stdMaster.OrderBy(x => x.StdId).ToArray() ;
break;
case "StdName":
stdMaster = stdMaster.OrderBy(x => x.StdName).ToArray();
break;
case "Email":
stdMaster = stdMaster.OrderBy(x => x.Email).ToArray();
break;
case "Phone":
stdMaster = stdMaster.OrderBy(x => x.Phone).ToArray();
break;
case "Address":
stdMaster = stdMaster.OrderBy(x => x.Address).ToArray();
break;
}
}
else
{
ImageSortname = "Images/sortAsc.png";
ids = 0;
switch (SortColumn)
{
case "StdId":
stdMaster = stdMaster.OrderByDescending(x => x.StdId).ToArray();
break;
case "StdName":
stdMaster = stdMaster.OrderByDescending(x => x.StdName).ToArray();
break;
case "Email":
stdMaster = stdMaster.OrderByDescending(x => x.Email).ToArray();
break;
case "Phone":
stdMaster = stdMaster.OrderByDescending(x => x.Phone).ToArray();
break;
case "Address":
stdMaster = stdMaster.OrderByDescending(x => x.Address).ToArray();
break;
}
}
}
筛选方法
在每个列标题部分,我们添加了一个新行,用于对 HTML 表格进行筛选。在每个列筛选 `Textbox` 的更改事件中,我们传递 `Textbox` 值。我们调用一个通用的筛选方法 `studentFilteringList`,并在该方法中,我们传递筛选列的 `Textbox` 值和列名。
// For Filtering by Student Name
void OnstdNameChanged(UIChangeEventArgs args)
{
string values = args.Value.ToString();
studentFilteringList(values, "StudentName");
}
// For Filtering by Email
void OnEmailChanged(UIChangeEventArgs args)
{
string values = args.Value.ToString();
studentFilteringList(values, "Email");
}
// For Filtering by Phone
void OnPhoneChanged(UIChangeEventArgs args)
{
string values = args.Value.ToString();
studentFilteringList(values, "Phone");
}
// For Filtering by Adress
void OnAddressChanged(UIChangeEventArgs args)
{
string values = args.Value.ToString();
studentFilteringList(values, "Address");
}
在这里,我们创建了一个名为 `studentFilteringList` 的通用函数,在该方法中,我们获取筛选列的 `Textbox` 值和列名。我们从 Web API 进行筛选,并将筛选结果绑定到 HTML 表格。
//Filtering
protected async Task studentFilteringList(String Value,string columnName)
{
stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");
if (Value.Trim().Length >0)
{
switch (columnName)
{
case "StudentName":
stdMaster = stdMaster.Where(x => x.StdName.Contains(Value)).ToArray();
break;
case "Email":
stdMaster = stdMaster.Where(x => x.Email.Contains(Value)).ToArray();
break;
case "Phone":
stdMaster = stdMaster.Where(x => x.Phone.Contains(Value)).ToArray();
break;
case "Address":
stdMaster = stdMaster.Where(x => x.Address.Contains(Value)).ToArray();
break;
default:
stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");
break;
}
}
else
{
stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");
}
}
具有动态内容的 Razor 页面
首先,我们需要添加新的 Razor 视图页面。
添加 Razor 视图
要添加 Razor 视图页面,请右键单击 `Client` 项目中的 _Pages_ 文件夹。单击“添加”>>“新建项”。
选择 Razor View >> 输入您的页面名称。在这里,我们将其命名为 _Students.chtml_。
与我们之前的 Razor 视图页面一样,我们使用相同的逻辑来绑定主表格和明细表格。但在这里,我们不是直接绑定 HTML 来显示明细表格,而是使用 Blazor 动态内容来绑定明细表格的结果。我们已经看到了主数据绑定和切换按钮单击事件,现在对于此页面,我们将仅直接解释动态内容部分。
动态内容绑定 HTML 部分
与我们之前的页面一样,我们进行所有状态检查,最后绑定动态内容以显示明细 HTML 表格。我们使用 `@DynamicContent` 对象来绑定动态内容的结果。
@if (stdDetail != null)
{
@if (showDetailStatus == 1)
{
@if (@StudentMasters.StdId == studentIDs)
{
<tr style="background-color:#6D7B8D ; color:honeydew ;border-style:dashed;
border-width:2px;border-color:#ECF3F4;">
<td colspan="6" align="center">
Student Details of Student Id - <strong> @StudentMasters.StdId </strong> ,
Total @stdDetail.Length Grade details for this Student
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
@DynamicContent
</td>
</tr>
}
}
}
动态内容绑定函数
我们使用 `RenderFragment` 对象来绑定动态内容结果。在我们的方法中使用 `RenderFragment` (Delegate) ,我们构建动态内容,并在运行时动态绑定结果。
private Microsoft.AspNetCore.Blazor.RenderFragment DynamicContent;
在明细 HTML 表格绑定的方法中,我们创建动态内容以在主表格内显示明细表格。在调用方法中,每次我们动态创建明细表格,并使用构建器在 `RenderFragment` 委托中绑定结果,我们动态创建表格并绑定结果。
stdDetail = await Http.GetJsonAsync<StudentDetails[]>
("/api/StudentDetails/" + Convert.ToInt32(StudID));
DynamicContent = builder =>
{
var seq = 0;
builder.OpenElement(seq, "table");
builder.AddAttribute(seq, "style", "background-color:#ECF3F4;border-style:dashed;
border-width:2px;border-color:#0A2464; padding:5px;width:100%;table-layout:fixed;");
// Heading
builder.OpenElement(++seq, "tr");
builder.AddAttribute(++seq, "style", "height: 30px;border-style:inset;border-width:1px;
border-color:#6D7B8D; background-color:#336699 ; color:#FFFFFF ;");
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, "Student Details");
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, "Major");
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, "Year");
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, "Term");
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, "Grade");
builder.CloseElement();
builder.CloseElement();
//Tbody
foreach (var stdDtls in stdDetail)
{
builder.OpenElement(++seq, "tr");
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, stdDtls.StdDtlId);
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, stdDtls.Major);
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, stdDtls.Year);
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, stdDtls.Term);
builder.CloseElement();
builder.OpenElement(++seq, "td");
builder.AddContent(++seq, stdDtls.Grade);
builder.CloseElement();
builder.CloseElement();
}
builder.CloseElement();
};
构建并运行应用程序
关注点
在本文中,我们仅添加了一级表格层级。您可以将其扩展到创建多级 HTML 表格。请注意,在创建 `DBContext` 和设置连接字符串时,不要忘记添加您的 SQL 连接字符串。希望您喜欢这篇文章。在下一篇文章中,我们将看到更多关于 Blazor 的示例,使用 Blazor 确实非常棒!
历史
- 2018年6月10日:BlazorMasterDetailGrid.zip