使用复杂 object 的嵌套 asp 中继器
Nested asp repeaters using complex object
我有一个复杂的 object,其中嵌套了 collection 个 object,需要绑定到 table 中的 repeater/shown。 Object 显示 14 个项目:
我想这样显示数据:
Objects 看起来像:
我需要在 table/column header 中显示“FieldName”,在 table 行中显示“FieldValue”。注意第 3 项和第 5 项都是“Phone Number”FieldName。所以我需要 PhoneNumber 显示一次(在 header 列中)然后会有 2 行显示 2 个电话号码字段值(如 table 屏幕截图中所示)。因此 collection 中可能有多组项目。 N 个联系人等。我不确定如何设置中继器(或使用多少个)和/或如何设置中继器 OnItemDataBound。任何指向正确方向的想法或伪代码都会非常有帮助。
更新:
调用 API 响应 returns 列表(即联系人)
属性objects(示例):
1st item: FieldName = "Name" FieldValue = "Mike Jones"
2nd item: FieldName = "Phone Number" FieldValue = "999-999-9999"
3rd item: FieldName = "Address" FieldValue = "123 Main St"
4th item: FieldName = "Name" FieldValue = "Mary Price"
5th item: FieldName = "Phone Number" FieldValue = "888-999-7777"
6th item: FieldName = "Address" FieldValue = "789 Broadway St"
标记需要显示 table:
-------------------------------------------------
|Name | Phone Number | Address |
-------------------------------------------------
|Mike Jones | 999-999-9999 | 123 Main St |
-------------------------------------------------
|Mary Price | 888-999-7777 | 789 Broadway St |
-------------------------------------------------
好的,所以问题很简单:
我有一个名字列表,对于每个名字,我可能有 child table 个 phone 个数字。他们可能没有 phone 个号码,他们可能有 5 个 phone 个号码。
什么是显示此主记录的好方法,然后是每行的重复 child 记录?
有很多方法可以做到这一点。我经常建议对于行的主要显示,我们使用列表视图,然后为 child 行嵌套一个网格视图。
然而,一如既往,哪条路将取决于多少数据,以及child数据显示必须有多少行(复杂)?
但是,让我们使用一个简单的网格。由于这样的设置变得更加复杂,因此我强烈建议使用列表视图。列表视图更好,因为它在布局方面更加灵活。虽然“设置”是更多的标记,但为每一行添加新列和复杂控件要好得多。在较长的 运行 列表视图中,实际上可以减少整体标记。
但是,我们只有两列额外的“child 重复”数据。
所以我们实际上是这样的:
table people - our list of contacts/people
table Phones - our child list of phone numbers for each "people".
那么,让我们与 table 人一起组建一个网格。我会经常启动并让向导创建那个网格。然后我在网页中清除(删除)数据源,然后开始使用删除键删除多余的垃圾。
所以,我们现在有了这个标记:
<div style="width:30%">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
</Columns>
</asp:GridView>
</div>
我们填充这个网格的代码是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
DataTable rst = MyRst("SELECT * from People Order by FirstName");
GridView1.DataSource = rst;
GridView1.DataBind();
}
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
return rstData;
}
我们的输出是这样的:
好的,所以我们当然有这个设置:
现在,我们可以进行查询连接,但话又说回来,这将重复每个 child 行的主行(然后我们将不得不“隐藏”它。
所以,让我们转到标记并添加两行。
(电话类型和电话号码)。
所以我们现在有这个:
<div style="width:40%">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Type">
<ItemTemplate>
<asp:label ID="txtType" runat="server" Text = '<%# Eval("PhoneType") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Phone">
<ItemTemplate>
<asp:label ID="txtPhone" runat="server" Text = '<%# Eval("Phone") %>' ></asp:label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
(这就是我使用 gridview 的意思 - 放入 nice plane jane asp.net 控件(在这种情况下是一个标签),你必须用 itemtemplate 包围它 - 我发现有点如果你有“很多”列会很痛苦。所以如果你需要很多自定义列,那么列表视图会更好。但到目前为止我们还不错。
所以,我们的代码现在变成了这样:
我们只需拉取每个 child 行的数据,并将此 child table 的结果推入我们添加的两个新列中。
这个:
void LoadGrid()
{
DataTable rst = MyRst("SELECT * from People Order by FirstName");
rst.Columns.Add("PhoneType", typeof(string));
rst.Columns.Add("Phone", typeof(string));
foreach (DataRow OneRow in rst.Rows)
{
// get child rows for this main row
DataTable ChildRows = MyRst("SELECT * from Phones where People_ID = " + OneRow["ID"]);
foreach (DataRow ChildRow in ChildRows.Rows)
{
if (OneRow["PhoneType"].ToString() != "")
{
// start new line in this cell
OneRow["PhoneType"] += "<br/>";
OneRow["Phone"] += "<br/>";
}
OneRow["PhoneType"] += ChildRow["PhoneType"].ToString();
OneRow["Phone"] += ChildRow["PhoneNumber"].ToString();
}
}
GridView1.DataSource = rst;
GridView1.DataBind();
}
所以这是一些额外的循环代码!事实上,在大多数情况下,如果我们正在编写循环代码,那么我们往往会以错误的方式这样做。
我们现在有这个:
这也取决于我们想在这里做什么。假设我们需要每个 child phone 号码的点击按钮(可能还包括一封电子邮件)。所以如果我们必须点击 child email/phone 来采取行动,那么显然上述方法有点快速和肮脏,但不会让我们能够点击特定的 phone 编号行到 select.
所以,如果出于某种原因我们想要一个点击事件,或者按钮到 select 给定的 child 行?
然后我会转向嵌套 child 网格。因此,我们不需要循环来填充 child 数据 - 但实际上会以类似的方式将新网格绑定到我们构建主网格的方式。
如前所述,我可能会跳转到主网格的列表视图。
如果您愿意,我可以并且会 post 一个在列表视图中嵌套网格视图的工作示例 - 比如说用一个额外的按钮点击 child 行作为“我们可能想采取的行动”。
我有一个复杂的 object,其中嵌套了 collection 个 object,需要绑定到 table 中的 repeater/shown。 Object 显示 14 个项目:
我想这样显示数据:
Objects 看起来像:
我需要在 table/column header 中显示“FieldName”,在 table 行中显示“FieldValue”。注意第 3 项和第 5 项都是“Phone Number”FieldName。所以我需要 PhoneNumber 显示一次(在 header 列中)然后会有 2 行显示 2 个电话号码字段值(如 table 屏幕截图中所示)。因此 collection 中可能有多组项目。 N 个联系人等。我不确定如何设置中继器(或使用多少个)和/或如何设置中继器 OnItemDataBound。任何指向正确方向的想法或伪代码都会非常有帮助。
更新: 调用 API 响应 returns 列表(即联系人)
属性objects(示例):
1st item: FieldName = "Name" FieldValue = "Mike Jones"
2nd item: FieldName = "Phone Number" FieldValue = "999-999-9999"
3rd item: FieldName = "Address" FieldValue = "123 Main St"
4th item: FieldName = "Name" FieldValue = "Mary Price"
5th item: FieldName = "Phone Number" FieldValue = "888-999-7777"
6th item: FieldName = "Address" FieldValue = "789 Broadway St"
标记需要显示 table:
-------------------------------------------------
|Name | Phone Number | Address |
-------------------------------------------------
|Mike Jones | 999-999-9999 | 123 Main St |
-------------------------------------------------
|Mary Price | 888-999-7777 | 789 Broadway St |
-------------------------------------------------
好的,所以问题很简单:
我有一个名字列表,对于每个名字,我可能有 child table 个 phone 个数字。他们可能没有 phone 个号码,他们可能有 5 个 phone 个号码。
什么是显示此主记录的好方法,然后是每行的重复 child 记录?
有很多方法可以做到这一点。我经常建议对于行的主要显示,我们使用列表视图,然后为 child 行嵌套一个网格视图。
然而,一如既往,哪条路将取决于多少数据,以及child数据显示必须有多少行(复杂)?
但是,让我们使用一个简单的网格。由于这样的设置变得更加复杂,因此我强烈建议使用列表视图。列表视图更好,因为它在布局方面更加灵活。虽然“设置”是更多的标记,但为每一行添加新列和复杂控件要好得多。在较长的 运行 列表视图中,实际上可以减少整体标记。
但是,我们只有两列额外的“child 重复”数据。
所以我们实际上是这样的:
table people - our list of contacts/people
table Phones - our child list of phone numbers for each "people".
那么,让我们与 table 人一起组建一个网格。我会经常启动并让向导创建那个网格。然后我在网页中清除(删除)数据源,然后开始使用删除键删除多余的垃圾。
所以,我们现在有了这个标记:
<div style="width:30%">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
</Columns>
</asp:GridView>
</div>
我们填充这个网格的代码是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
DataTable rst = MyRst("SELECT * from People Order by FirstName");
GridView1.DataSource = rst;
GridView1.DataBind();
}
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
return rstData;
}
我们的输出是这样的:
好的,所以我们当然有这个设置:
现在,我们可以进行查询连接,但话又说回来,这将重复每个 child 行的主行(然后我们将不得不“隐藏”它。
所以,让我们转到标记并添加两行。 (电话类型和电话号码)。
所以我们现在有这个:
<div style="width:40%">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Type">
<ItemTemplate>
<asp:label ID="txtType" runat="server" Text = '<%# Eval("PhoneType") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Phone">
<ItemTemplate>
<asp:label ID="txtPhone" runat="server" Text = '<%# Eval("Phone") %>' ></asp:label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
(这就是我使用 gridview 的意思 - 放入 nice plane jane asp.net 控件(在这种情况下是一个标签),你必须用 itemtemplate 包围它 - 我发现有点如果你有“很多”列会很痛苦。所以如果你需要很多自定义列,那么列表视图会更好。但到目前为止我们还不错。
所以,我们的代码现在变成了这样: 我们只需拉取每个 child 行的数据,并将此 child table 的结果推入我们添加的两个新列中。
这个:
void LoadGrid()
{
DataTable rst = MyRst("SELECT * from People Order by FirstName");
rst.Columns.Add("PhoneType", typeof(string));
rst.Columns.Add("Phone", typeof(string));
foreach (DataRow OneRow in rst.Rows)
{
// get child rows for this main row
DataTable ChildRows = MyRst("SELECT * from Phones where People_ID = " + OneRow["ID"]);
foreach (DataRow ChildRow in ChildRows.Rows)
{
if (OneRow["PhoneType"].ToString() != "")
{
// start new line in this cell
OneRow["PhoneType"] += "<br/>";
OneRow["Phone"] += "<br/>";
}
OneRow["PhoneType"] += ChildRow["PhoneType"].ToString();
OneRow["Phone"] += ChildRow["PhoneNumber"].ToString();
}
}
GridView1.DataSource = rst;
GridView1.DataBind();
}
所以这是一些额外的循环代码!事实上,在大多数情况下,如果我们正在编写循环代码,那么我们往往会以错误的方式这样做。
我们现在有这个:
这也取决于我们想在这里做什么。假设我们需要每个 child phone 号码的点击按钮(可能还包括一封电子邮件)。所以如果我们必须点击 child email/phone 来采取行动,那么显然上述方法有点快速和肮脏,但不会让我们能够点击特定的 phone 编号行到 select.
所以,如果出于某种原因我们想要一个点击事件,或者按钮到 select 给定的 child 行?
然后我会转向嵌套 child 网格。因此,我们不需要循环来填充 child 数据 - 但实际上会以类似的方式将新网格绑定到我们构建主网格的方式。
如前所述,我可能会跳转到主网格的列表视图。
如果您愿意,我可以并且会 post 一个在列表视图中嵌套网格视图的工作示例 - 比如说用一个额外的按钮点击 child 行作为“我们可能想采取的行动”。