使用嵌套ASP Repeater绑定复杂对象实现动态表格的方案咨询
实现方案
核心思路
首先需要把API返回的扁平键值对结构,先转换为按联系人分组的结构化数据,再绑定到Repeater渲染即可。动态列场景总共只需要3层Repeater,固定列场景仅需1层Repeater即可实现。
前置准备:数据结构转换
首先定义API返回的单个字段项实体:
public class ApiContactField { public string FieldName { get; set; } public string FieldValue { get; set; } }
第一步先对返回的字段列表做结构化处理:
// 页面级全局变量,存储去重后的列名,顺序和API返回一致 private List<string> _columnNames; protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack) { // 假设apiResult是接口返回的List<ApiContactField> List<ApiContactField> apiResult = GetApiContactsData(); // 1. 提取去重列名 _columnNames = apiResult.Select(x => x.FieldName).Distinct().ToList(); // 2. 按列数拆分扁平列表,组装为联系人分组数据 List<Dictionary<string, string>> structuredContacts = new List<Dictionary<string, string>>(); int columnCount = _columnNames.Count; for(int i = 0; i < apiResult.Count; i += columnCount) { Dictionary<string, string> contact = new Dictionary<string, string>(); for(int j = 0; j < columnCount; j++) { contact[_columnNames[j]] = apiResult[i + j].FieldValue; } structuredContacts.Add(contact); } // 绑定数据到Repeater rptTableHeader.DataSource = _columnNames; rptTableHeader.DataBind(); rptContactRows.DataSource = structuredContacts; rptContactRows.DataBind(); } }
场景1:动态列适配(字段数量不固定)
前端代码
<table style="border-collapse: collapse;" border="1" cellpadding="6"> <thead> <tr> <!-- 表头Repeater:渲染所有列名 --> <asp:Repeater ID="rptTableHeader" runat="server"> <ItemTemplate> <th><%# Container.DataItem.ToString() %></th> </ItemTemplate> </asp:Repeater> </tr> </thead> <tbody> <!-- 数据行Repeater:渲染每个联系人的行 --> <asp:Repeater ID="rptContactRows" runat="server" OnItemDataBound="rptContactRows_ItemDataBound"> <ItemTemplate> <tr> <!-- 行内字段Repeater:渲染当前行的每个单元格值 --> <asp:Repeater ID="rptCellValues" runat="server" OnItemDataBound="rptCellValues_ItemDataBound"> <ItemTemplate> <td> <asp:Literal ID="ltCellValue" runat="server"/> </td> </ItemTemplate> </asp:Repeater> </tr> </ItemTemplate> </asp:Repeater> </tbody> </table>
绑定事件代码
protected void rptContactRows_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { // 获取当前行的联系人数据 var currentContact = (Dictionary<string, string>)e.Item.DataItem; // 找到当前行的单元格Repeater var rptCellValues = (Repeater)e.Item.FindControl("rptCellValues"); // 绑定列名作为数据源,按顺序渲染单元格 rptCellValues.DataSource = _columnNames; rptCellValues.DataBind(); } } protected void rptCellValues_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { // 获取当前列名 string currentCol = e.Item.DataItem.ToString(); // 获取父级行的联系人数据 var parentRow = (RepeaterItem)e.Item.NamingContainer.NamingContainer; var currentContact = (Dictionary<string, string>)parentRow.DataItem; // 赋值单元格内容 var ltCellValue = (Literal)e.Item.FindControl("ltCellValue"); ltCellValue.Text = currentContact[currentCol]; } }
场景2:固定列适配(确定只有姓名、电话、地址3个字段)
如果字段固定无需动态适配,可以简化为1层Repeater,无需写绑定事件:
前端代码
<table style="border-collapse: collapse;" border="1" cellpadding="6"> <thead> <tr> <th>Name</th> <th>Phone Number</th> <th>Address</th> </tr> </thead> <tbody> <asp:Repeater ID="rptContacts" runat="server"> <ItemTemplate> <tr> <td><%# Eval("Name") %></td> <td><%# Eval("PhoneNumber") %></td> <td><%# Eval("Address") %></td> </tr> </ItemTemplate> </asp:Repeater> </tbody> </table>
数据绑定代码
可以先定义强类型联系人实体,预处理时直接转成实体列表绑定即可:
public class Contact { public string Name { get; set; } public string PhoneNumber { get; set; } public string Address { get; set; } } // Page_Load中的预处理逻辑调整为: List<Contact> structuredContacts = new List<Contact>(); int columnCount = _columnNames.Count; for(int i = 0; i < apiResult.Count; i += columnCount) { Contact contact = new Contact { Name = apiResult[i].FieldValue, PhoneNumber = apiResult[i+1].FieldValue, Address = apiResult[i+2].FieldValue }; structuredContacts.Add(contact); } rptContacts.DataSource = structuredContacts; rptContacts.DataBind();
内容的提问来源于stack exchange,提问作者obautista
相关产品推荐
相关产品推荐

