[英]Fill nested repeaters in a table
I have a repeater inside another repeater. 我在另一个中继器内有一个中继器。 How can I display all the fields(surname) from db in an inner repeater.
如何在内部中继器中显示db中的所有字段(姓)。 In the function
outerRepeater_ItemDataBound
, DataSource
isn't recognized. 在函数
outerRepeater_ItemDataBound
,无法识别DataSource
。 I don't know exactly where I need to select all the surnames for a specific name. 我不知道确切要为特定名称选择所有姓氏的位置。
I have this in my repeater.ascx: 我在repeater.ascx中有这个:
<form id="form1" runat="server">
<div>
<asp:Repeater runat="server" ID="outerRepeater" OnItemDataBound="outerRepeater_ItemDataBound">
<HeaderTemplate>
<table>
<td><th>Name:</th></td>
<td><th>Surname:</th></td>
</table>
</HeaderTemplate>
<ItemTemplate>
<h3><%#DataBinder.Eval(Container.DataItem,"Name")%></h3>
<asp:Repeater runat="server" ID="innerRepeater" >
<ItemTemplate>
<%#Eval("Surname") %>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
</div>
</form>
And this in repeater.ascx.cs 这在repeater.ascx.cs中
public partial class Repeater : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
outerRepeater.DataSource = GetDataSource();
outerRepeater.DataBind();
}
private DataTable GetDataSource()
{
SqlConnection myConnection = new SqlConnection(@"my connection string");
SqlDataAdapter myCommand = new SqlDataAdapter("SELECT Distinct Name FROM Person ORDER BY Name ", myConnection);
DataTable dt = new DataTable();
myCommand.Fill(dt);
myConnection.Close();
return dt;
}
private void Page_Init(object sender, EventArgs e)
{
InitializeComponent();
}
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
protected void outerRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
Repeater innerRepeater = e.Item.FindControl("innerRepeater") as Repeater;
DataTable dt = GetSurname();
innerRepeater.DataSource = dt;//here isn't su
innerRepeater.DataBind();
}
}
private DataTable GetSurname()
{
SqlConnection myConnection = new SqlConnection(@"my connection string");
SqlDataAdapter da = new SqlDataAdapter("Select Surname from Person ", myConnection);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
I am not sure that you really need to set Page_Load
event handler in your code-behind. 我不确定您是否真的需要在后台代码中设置
Page_Load
事件处理程序。 With default page settings it will be wired-up automatically. 使用默认页面设置,它将自动连接。
Setting it manually is required only if you set the PagesSection.AutoEventWireup to false. 仅当将PagesSection.AutoEventWireup设置为false时,才需要手动设置它。
It is possible to create a table with repeater - How to create a three column table in ASP.Net Repeater , but it will require a bit different markup with properly set table tags: 可以使用Repeater创建一个表- 如何在ASP.Net Repeater中创建三列表 ,但是需要使用正确设置的表标记进行一些不同的标记:
<asp:Repeater runat="server" ID="outerRepeater" OnItemDataBound="outerRepeater_ItemDataBound">
<HeaderTemplate>
<table>
<thead>
<th>Name:</th>
<th>Surname:</th>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<h3><%#DataBinder.Eval(Container.DataItem,"Name")%></h3>
</td>
<td>
<asp:Repeater runat="server" ID="innerRepeater" >
<ItemTemplate>
<%#Eval("Surname") %>
</ItemTemplate>
</asp:Repeater>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
And, perhaps, GridView is a better alternative to manual table creation. 而且,也许GridView是手动创建表的更好选择。
You obviously get all surnames because Select Surname from People
doesn't filter anything - it just selects all items. 您显然会得到所有姓氏,因为
Select Surname from People
中Select Surname from People
不会过滤任何内容-它只会选择所有项。 To achieve what you want you will have to add some WHERE clause , that filter by name associated with the current row. 为了实现所需的功能,您将必须添加一些WHERE子句 ,该子句将按与当前行关联的名称进行过滤。 The
Name
can be obtained through the e.Item.DataItem
in the outerRepeater_ItemDataBound
handler. 可以通过
outerRepeater_ItemDataBound
处理程序中的e.Item.DataItem
获得Name
。
protected void outerRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
Repeater innerRepeater = e.Item.FindControl("innerRepeater") as Repeater;
String name = ((DataRowView)e.Item.DataItem)[0].ToString();
DataTable dt = GetSurname(name);
innerRepeater.DataSource = dt;//here isn't su
innerRepeater.DataBind();
}
}
private DataTable GetSurname(String name)
{
using (SqlConnection myConnection = new SqlConnection(@"Data Source=(LocalDb)\v11.0; Database = TSQL2012"))
{
using (SqlDataAdapter da = new SqlDataAdapter("Select Surname from Person WHERE Name = @name", myConnection))
{
da.SelectCommand.Parameters.AddWithValue("@name", name);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
}
While you call the Close
method on your connections it is better to use the using
clause as it used in the previous code samples, because using
will guarantee that whatever happens the connection will be closed for sure. 当您在连接上调用
Close
方法时,最好使用using
子句,就像在先前代码示例中使用的那样,因为using
可以确保无论发生什么情况,连接都将被确定关闭。 The same applies as well to the SqlDataAdapter
, but whether it is actually required or just a good rule of thumb I do not know. 这同样适用于
SqlDataAdapter
,但是我不知道它是实际上必需的还是只是一个很好的经验法则。
Multiple SQL requests, especially when all the required information is directly related can lead to a very poor performance. 多个SQL请求,尤其是在所有必需信息都直接相关的情况下,可能会导致非常差的性能。 You can either fetch all the names and surnames to process them in the page, or you can apply Optimal way to concatenate/aggregate strings to fetch single datatable with all the needed data:
您可以获取所有名称和姓氏以在页面中对其进行处理,也可以应用最佳方式来串联/聚合字符串以获取具有所有所需数据的单个数据表:
aspx: ASPX:
<asp:Repeater runat="server" ID="outerRepeater">
...
<ItemTemplate>
<tr >
<td>
<h3><%#DataBinder.Eval(Container.DataItem,"Name")%></h3>
</td>
<td>
<label><%#DataBinder.Eval(Container.DataItem,"ConcatenatedSurnames")%></label>
</td>
</tr>
</ItemTemplate>
Code-behind: 代码隐藏:
private const String SelectCommand = @"
WITH Partitioned AS
(
SELECT Name,
Surname,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name) AS NameNumber,
COUNT(*) OVER (PARTITION BY Name ORDER BY Name) AS NameCount
FROM Person
),
Concatenated AS
(
SELECT Name,
CAST(Surname AS nvarchar) AS ConcatenatedSurnames,
NameNumber,
NameCount
FROM Partitioned
WHERE NameNumber = 1
UNION ALL
SELECT
P.Name,
CAST(C.ConcatenatedSurnames + ', ' + P.Surname AS nvarchar),
P.NameNumber,
P.NameCount
FROM Partitioned AS P
INNER JOIN Concatenated AS C
ON P.Name = C.Name AND
P.NameNumber = C.NameNumber + 1
)
SELECT
Name,
ConcatenatedSurnames
FROM Concatenated
WHERE NameNumber = NameCount";
private DataTable GetDataSource()
{
using (SqlConnection myConnection = new SqlConnection(@"Data Source=(LocalDb)\v11.0; Database = TSQL2012"))
{
using (SqlDataAdapter myCommand = new SqlDataAdapter(SelectCommand, myConnection))
{
DataTable dt = new DataTable();
myCommand.Fill(dt);
return dt;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.