简体   繁体   English

在表格中填充嵌套的中继器

[英]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;
    }

1. Manually adding `Page_Load` handler 1.手动添加`Page_Load`处理程序

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时,才需要手动设置它。

2. Table with repeater 2.带直放站的桌子

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是手动创建表的更好选择。

3. Get all surnames for the given name 3.获取给定名称的所有姓氏

You obviously get all surnames because Select Surname from People doesn't filter anything - it just selects all items. 您显然会得到所有姓氏,因为Select Surname from PeopleSelect 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;
        }
    }
}

4. Not always disposing the connection 4.并非总是布置连接

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 ,但是我不知道它是实际上必需的还是只是一个很好的经验法则。

5. Multiple SQL requests 5.多个SQL请求

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM