如何在Razor页面实现正确嵌套分组及统计功能?
解决方案:Razor页面嵌套分组与小计/总计实现
核心问题分析
你遇到的ArrestOfficer在每个ArrestDept下重复显示的问题,本质是没有在后端对数据进行正确的关联分组,前端视图直接遍历全量数据,自然会出现所有Officer绑定到每个Dept的情况。视图仅负责数据展示,过滤、分组这类逻辑必须在后端处理,否则不仅逻辑混乱,还会带来性能损耗。
步骤1:后端整理分组数据
在Razor页面的.cs文件(PageModel)中,用LINQ对原始数据进行嵌套分组,确保每个ArrestDept下只包含属于它的ArrestOfficer,同时提前计算各级合计值,避免前端重复计算。
示例代码:
public class ArrestReportModel : PageModel { // 假设原始数据模型是Arrecord,包含ArrestDept、ArrestOfficer、Amount等字段 public List<DeptGroup> GroupedData { get; set; } public decimal TotalGrand { get; set; } public void OnGet() { // 模拟原始数据,实际从数据库/接口获取 var rawData = new List<Arrecord> { new Arrecord { ArrestDept = "City A", ArrestOfficer = "Officer1", Amount = 100 }, new Arrecord { ArrestDept = "City A", ArrestOfficer = "Officer1", Amount = 200 }, new Arrecord { ArrestDept = "City A", ArrestOfficer = "Officer2", Amount = 150 }, new Arrecord { ArrestDept = "City B", ArrestOfficer = "Officer3", Amount = 300 }, new Arrecord { ArrestDept = "City B", ArrestOfficer = "Officer4", Amount = 250 } }; // 嵌套分组:先按Dept分组,再按Officer分组,同时计算每个Officer的小计 GroupedData = rawData .GroupBy(d => d.ArrestDept) .Select(deptGroup => new DeptGroup { DeptName = deptGroup.Key, OfficerGroups = deptGroup .GroupBy(o => o.ArrestOfficer) .Select(officerGroup => new OfficerGroup { OfficerName = officerGroup.Key, Entries = officerGroup.ToList(), OfficerTotal = officerGroup.Sum(x => x.Amount) }) .ToList(), DeptTotal = deptGroup.Sum(x => x.Amount) }) .ToList(); // 计算报表总计 TotalGrand = GroupedData.Sum(d => d.DeptTotal); } // 定义分组模型类 public class DeptGroup { public string DeptName { get; set; } public List<OfficerGroup> OfficerGroups { get; set; } public decimal DeptTotal { get; set; } } public class OfficerGroup { public string OfficerName { get; set; } public List<Arrecord> Entries { get; set; } public decimal OfficerTotal { get; set; } } // 原始数据模型 public class Arrecord { public string ArrestDept { get; set; } public string ArrestOfficer { get; set; } public decimal Amount { get; set; } // 其他字段... } }
步骤2:前端视图展示分组与合计
在.cshtml文件中,遍历后端传递的分组数据,依次展示Dept、Officer、明细,以及各级合计:
示例代码:
<table class="table table-bordered"> <thead> <tr> <th>部门</th> <th>警员</th> <th>金额</th> <!-- 其他列... --> </tr> </thead> <tbody> @foreach (var dept in Model.GroupedData) { <!-- 部门行 --> <tr> <td rowspan="@(dept.OfficerGroups.Sum(o => o.Entries.Count) + dept.OfficerGroups.Count + 1)"> @dept.DeptName </td> </tr> @foreach (var officer in dept.OfficerGroups) { <!-- 警员行 --> <tr> <td rowspan="@(officer.Entries.Count + 1)">@officer.OfficerName</td> </tr> <!-- 明细行 --> @foreach (var entry in officer.Entries) { <tr> <td>@entry.Amount</td> <!-- 其他列... --> </tr> } <!-- 警员小计行 --> <tr> <td><strong>警员小计: @officer.OfficerTotal</strong></td> </tr> } <!-- 部门总计行 --> <tr> <td><strong>部门总计: @dept.DeptTotal</strong></td> </tr> } </tbody> <tfoot> <tr> <td colspan="2"><strong>报表总计: @Model.TotalGrand</strong></td> </tr> </tfoot> </table>
关键说明
- 为什么不能仅靠视图实现?视图的职责是展示数据,而非处理业务逻辑。如果在视图中通过循环过滤数据,不仅会写出冗余代码,还会因为遍历全量数据导致性能下降,尤其数据量大时问题更明显。后端提前分组计算,既符合MVC的职责分离原则,也能提升页面渲染效率。
- 分组逻辑采用LINQ的
GroupBy嵌套,确保数据关联正确,从根源解决Officer重复显示的问题。 - 各级合计值在后端提前计算,前端直接展示即可,避免前端重复计算带来的性能开销和逻辑错误。
内容的提问来源于stack exchange,提问作者MelB
相关产品推荐
相关产品推荐

