繁体   English   中英

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

[英]Fill nested repeaters in a table

我在另一个中继器内有一个中继器。 如何在内部中继器中显示db中的所有字段(姓)。 在函数outerRepeater_ItemDataBound ,无法识别DataSource 我不知道确切要为特定名称选择所有姓氏的位置。

我在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>

这在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.手动添加`Page_Load`处理程序

我不确定您是否真的需要在后台代码中设置Page_Load事件处理程序。 使用默认页面设置,它将自动连接。

仅当将PagesSection.AutoEventWireup设置为false时,才需要手动设置它。

2.带直放站的桌子

可以使用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>

而且,也许GridView是手动创建表的更好选择。

3.获取给定名称的所有姓氏

您显然会得到所有姓氏,因为Select Surname from PeopleSelect Surname from People不会过滤任何内容-它只会选择所有项。 为了实现所需的功能,您将必须添加一些WHERE子句 ,该子句将按与当前行关联的名称进行过滤。 可以通过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.并非总是布置连接

当您在连接上调用Close方法时,最好使用using子句,就像在先前代码示例中使用的那样,因为using可以确保无论发生什么情况,连接都将被确定关闭。 这同样适用于SqlDataAdapter ,但是我不知道它是实际上必需的还是只是一个很好的经验法则。

5.多个SQL请求

多个SQL请求,尤其是在所有必需信息都直接相关的情况下,可能会导致非常差的性能。 您可以获取所有名称和姓氏以在页面中对其进行处理,也可以应用最佳方式来串联/聚合字符串以获取具有所有所需数据的单个数据表:

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>

代码隐藏:

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