Blazor Bootstrap v3.3.1详情视图展开触发事件的实现方法
在Blazor Bootstrap v3.3.1中实现展开详情视图时触发API调用
Blazor Bootstrap v3.3.1的Grid组件目前没有内置的"详情展开"事件,但可以通过以下两种简便方式实现需求:
方法一:监听Grid的ExpandedItems集合变化
Grid组件会自动维护ExpandedItems集合,记录当前展开的行数据。我们可以绑定这个集合,在组件渲染后检查新增的展开项,触发API调用:
修改后的代码示例
<Grid TItem="Employee1" Class="table table-hover border-top" Data="employees" AllowDetailView="true" @bind-ExpandedItems="expandedEmployees"> <!-- 绑定展开项集合 --> <!-- 原有列定义保持不变 --> <GridColumns> <GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id"> @context.Id </GridColumn> <GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name"> @context.Name </GridColumn> <GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation"> @context.Designation </GridColumn> <GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ"> @context.DOJ </GridColumn> <GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive"> @context.IsActive </GridColumn> </GridColumns> <!-- 原有详情视图内容保持不变 --> <GridDetailView TItem="Employee1"> <Grid TItem="Employee1" Class="table table-hover border-top" Data="employees" AllowDetailView="true"> <GridColumns> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Id" PropertyName="Id"> @emp1.Id </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Employee Name" PropertyName="Name"> @emp1.Name </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Designation" PropertyName="Designation"> @emp1.Designation </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="DOJ" PropertyName="DOJ"> @emp1.DOJ </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Active" PropertyName="IsActive"> @emp1.IsActive </GridColumn> </GridColumns> <GridDetailView TItem="Employee1" Context="emp1"> <div class="row"> <div class="col-2 fw-bold">Id</div> <div class="col">@emp1.Id</div> </div> <div class="row"> <div class="col-2 fw-bold">Name</div> <div class="col">@emp1.Name</div> </div> <div class="row"> <div class="col-2 fw-bold">Designation</div> <div class="col">@emp1.Designation</div> </div> <div class="row"> <div class="col-2 fw-bold">DOJ</div> <div class="col">@emp1.DOJ</div> </div> <div class="row"> <div class="col-2 fw-bold">IsActive</div> <div class="col">@emp1.IsActive</div> </div> </GridDetailView> </Grid> </GridDetailView> </Grid> @code { private List<Employee1> employees = new List<Employee1> { new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true } }; private List<Employee1> expandedEmployees = new(); private HashSet<int> processedExpandedIds = new(); // 避免重复触发API调用 protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) { // 筛选出新增的展开项 var newlyExpanded = expandedEmployees.Where(e => !processedExpandedIds.Contains(e.Id)).ToList(); foreach (var item in newlyExpanded) { // 执行API调用或其他业务操作 await LoadEmployeeDetails(item.Id); processedExpandedIds.Add(item.Id); } // 可选:处理收起的项,清理已记录的ID var removedIds = processedExpandedIds.Where(id => !expandedEmployees.Any(e => e.Id == id)).ToList(); foreach (var id in removedIds) { processedExpandedIds.Remove(id); } } await base.OnAfterRenderAsync(firstRender); } private async Task LoadEmployeeDetails(int employeeId) { // 替换为实际API调用逻辑 // var details = await _employeeApi.GetEmployeeDetailsAsync(employeeId); Console.WriteLine($"加载员工ID {employeeId} 的详情数据"); } public record class Employee1 { public int Id { get; set; } public string? Name { get; set; } public string? Designation { get; set; } public DateOnly DOJ { get; set; } public bool IsActive { get; set; } } }
方法二:自定义展开按钮,手动控制展开逻辑
替换Grid默认的展开图标,使用自定义按钮,点击时先执行API调用,再触发详情展开:
修改后的代码示例
<Grid TItem="Employee1" Class="table table-hover border-top" Data="employees" AllowDetailView="false"> <!-- 关闭默认展开逻辑 --> <GridColumns> <!-- 自定义展开按钮列 --> <GridColumn TItem="Employee1" Width="50"> <button type="button" class="btn btn-link p-0" @onclick="() => ToggleDetail(context)"> @(expandedEmployeeIds.Contains(context.Id) ? "▼" : "▶") </button> </GridColumn> <!-- 原有列定义保持不变 --> <GridColumn TItem="Employee1" HeaderText="Id" PropertyName="Id"> @context.Id </GridColumn> <GridColumn TItem="Employee1" HeaderText="Employee Name" PropertyName="Name"> @context.Name </GridColumn> <GridColumn TItem="Employee1" HeaderText="Designation" PropertyName="Designation"> @context.Designation </GridColumn> <GridColumn TItem="Employee1" HeaderText="DOJ" PropertyName="DOJ"> @context.DOJ </GridColumn> <GridColumn TItem="Employee1" HeaderText="Active" PropertyName="IsActive"> @context.IsActive </GridColumn> </GridColumns> <!-- 手动渲染详情视图 --> @foreach (var emp in employees) { if (expandedEmployeeIds.Contains(emp.Id)) { <tr> <td colspan="6"> <!-- 列数需与Grid总列数一致 --> <div class="p-3"> <Grid TItem="Employee1" Class="table table-hover border-top" Data="employees" AllowDetailView="true"> <GridColumns> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Id" PropertyName="Id"> @emp1.Id </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Employee Name" PropertyName="Name"> @emp1.Name </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Designation" PropertyName="Designation"> @emp1.Designation </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="DOJ" PropertyName="DOJ"> @emp1.DOJ </GridColumn> <GridColumn TItem="Employee1" Context="emp1" HeaderText="Active" PropertyName="IsActive"> @emp1.IsActive </GridColumn> </GridColumns> <GridDetailView TItem="Employee1" Context="emp1"> <div class="row"> <div class="col-2 fw-bold">Id</div> <div class="col">@emp1.Id</div> </div> <div class="row"> <div class="col-2 fw-bold">Name</div> <div class="col">@emp1.Name</div> </div> <div class="row"> <div class="col-2 fw-bold">Designation</div> <div class="col">@emp1.Designation</div> </div> <div class="row"> <div class="col-2 fw-bold">DOJ</div> <div class="col">@emp1.DOJ</div> </div> <div class="row"> <div class="col-2 fw-bold">IsActive</div> <div class="col">@emp1.IsActive</div> </div> </GridDetailView> </Grid> </div> </td> </tr> } } </Grid> @code { private List<Employee1> employees = new List<Employee1> { new Employee1 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, new Employee1 { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, new Employee1 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, new Employee1 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, new Employee1 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true } }; private HashSet<int> expandedEmployeeIds = new(); private async Task ToggleDetail(Employee1 employee) { if (expandedEmployeeIds.Contains(employee.Id)) { expandedEmployeeIds.Remove(employee.Id); } else { // 先执行API调用加载数据 await LoadEmployeeDetails(employee.Id); expandedEmployeeIds.Add(employee.Id); } StateHasChanged(); } private async Task LoadEmployeeDetails(int employeeId) { // 替换为实际API调用逻辑 Console.WriteLine($"加载员工ID {employeeId} 的详情数据"); } public record class Employee1 { public int Id { get; set; } public string? Name { get; set; } public string? Designation { get; set; } public DateOnly DOJ { get; set; } public bool IsActive { get; set; } } }
说明
- 方法一利用组件内置的
ExpandedItems集合,无需修改原有布局,适合需要保留默认展开样式的场景。 - 方法二完全自定义展开逻辑,灵活性更高,适合需要自定义按钮样式或添加额外交互的场景。
内容的提问来源于stack exchange,提问作者tuomis
相关产品推荐
相关产品推荐

