如何在asp.net中嵌套转发器

时间:2011-05-30 02:49:30

标签: c# asp.net data-binding repeater

我需要知道如何在用户控件中嵌套转发器。事情的html方面很好,这是我需要帮助的绑定和代码。我只能找到使用sql数据源的例子,这实际上并没有帮助。

我的中继器看起来像这样:

<asp:Panel ID="pnlDiscipline" runat="server" CssClass="">
    <asp:Repeater ID="rptDiscipline" runat="server">
        <ItemTemplate>
            <h4><%#Eval("Discipline")%></h4>
            <ul>
                <asp:Repeater ID="rptPrograms" runat="server">
                    <ItemTemplate>
                        <li><asp:HyperLink runat="server" Text='<%#Eval("Name") %>' NavigateUrl='<%#Eval("Link") %>'></asp:HyperLink> <%#Eval ("Notation") %></li>
                    </ItemTemplate>
                </asp:Repeater>
            </ul>
        </ItemTemplate>
    </asp:Repeater>

我需要做的是希望合理清楚 - h4规则应该出现一次,属于该学科的所有条目列在下面,然后是下一个h4,然后是相应的列表,下一个h4,依此类推。 / p>

数据源是在代码隐藏中创建的数据视图,其中每一行都有“名称”,“链接”,“NOtation”和“Discipline”。我已将数据视图绑定到最外层的转发器,并且它的行为符合预期 - 列表每个条目的学科名称,但在内部转发器中没有显示数据。

我该如何开展这项工作?

编辑:为了澄清,我在代码隐藏中有一个数据表。该表中的每一行都是一个项目,每个项目都属于一个学科。我想使用外部中继器列出学科,内部列出每个学科下分组的项目。像这样:

<h4>DISCIPLINE 1</h4>
    <ul>
        <li>Item</li>
        <li>Item</li>
        <li>Item</li>
    </ul>
<h4>DISCIPLINE 2</h4>
    <ul>        
        <li>Item</li>            
        <li>Item</li>
    </ul>
<h4>DISCIPLINE 3</h4>
    <ul>        
        <li>Item</li>            
        <li>Item</li>
    </ul>

目前,将数据表绑定到外部转发器会给出这个(示例使用上面的数据):

    <h4>DISCIPLINE 1</h4>
    <h4>DISCIPLINE 1</h4>
    <h4>DISCIPLINE 1</h4>
    <h4>DISCIPLINE 2</h4>
    <h4>DISCIPLINE 2</h4>
    <h4>DISCIPLINE 3</h4>
    <h4>DISCIPLINE 3</h4>

我按照建议在外部转发器上使用了OnItemDataBound,作为测试用例,我可以访问数据:

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{
    DataRowView drView = (DataRowView) e.Item.DataItem;
    string name = drView["Name"] as string;
    string link = drView["Link"] as string;
    string notation = drView["Notation"] as string;
    Response.Write(name + link + notation + "<br />")
}

所以数据就在那里,这正是我期望看到的,我只是无法将它绑定到内部转发器。如果有更高效的方法来实现同样的目标,我很乐意重新设计我的解决方案。

3 个答案:

答案 0 :(得分:7)

在外部控件上,使用ItemDataBound事件,如下所示:

<asp:Repeater ID="rptDiscipline" runat="server"
     OnItemDataBound="rptDiscipline_ItemDataBound">
...

然后,在代码隐藏中,处理rptDiscipline_ItemDataBound事件并手动绑定内部转发器。转发器的ItemDataBound事件会为每个重复的项触发一次。所以你会做这样的事情:

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{
    // To get your data item, cast e.Item.DataItem to 
    // whatever you're using for the data object; for example a DataRow.

    // Get the inner repeater:
    Repeater rptPrograms = (Repeater) e.Item.FindControl("rptPrograms");

    // Set the inner repeater's datasource to whatever it needs to be.
    rptPrograms.DataSource = ...
    rptPrograms.DataMember = ...
    rptPrograms.DataBind();
}

编辑:已更新以符合您的问题更新。

您需要将外部转发器绑定到一个数据源,该数据源每个项目只有一个记录,您希望转发器呈现。这意味着数据源需要是一个只包含其中的学科的集合/列表/数据表/等。在您的情况下,我建议从DataTable获取内部集合的List<string>个规则,并将外部转发器绑定到该集合。然后,内部转发器使用ItemDataBound事件绑定到DataTable中的数据子集。要获取子集,请通过DataView过滤DataTable。

这是代码:

protected void Page_Load(object sender, EventItems e)
{
    // get your data table
    DataTable table = ...

    if ( !IsPostBack )
    {
        // get a distinct list of disciplines
        List<string> disciplines = new List<string>();
        foreach ( DataRow row in table )
        {
            string discipline = (string) row["Discipline"];
            if ( !disciplines.Contains( discipline ) )
                disciplines.Add( discipline );
        }
        disciplines.Sort();

        // Bind the outer repeater
        rptDiscipline.DataSource = disciplines;
        rptDiscipline.DataBind();
    }
}

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{
    // To get your data item, cast e.Item.DataItem to 
    // whatever you're using for the data object
    string discipline = (string) e.Item.DataItem;

    // Get the inner repeater:
    Repeater rptPrograms = (Repeater) e.Item.FindControl("rptPrograms");

    // Create a filtered view of the data that shows only 
    // the disciplines needed for this row
    // table is the datatable that was originally bound to the outer repeater
    DataView dv = new DataView( table );  
    dv.RowFilter = String.Format("Discipline = '{0}'", discipline);

    // Set the inner repeater's datasource to whatever it needs to be.
    rptPrograms.DataSource = dv;
    rptPrograms.DataBind();
}   

答案 1 :(得分:4)

如果您不想在ItemDataBound事件上执行此操作,如果子属性是这样的集合,您也可以通过绑定到父项的子属性来在页面中内联:

<asp:Repeater runat="server" ID="OuterRepeater" >
    <ItemTemplate>
        Outer Content: <%# DataBinder.Eval(Container.DataItem, "ParentProperty")%>
        <asp:Repeater runat="server" ID="InnerRepeater" DataSource='<%# DataBinder.Eval(Container.DataItem, "ChildCollection")%>' >
            <ItemTemplate>
                <%# DataBinder.Eval(Container.DataItem, "ChildProperty")%>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

答案 2 :(得分:1)

首先,您需要两个列表,即学科列表,然后是所有数据列表。

数据将学科列表绑定到外部转发器。如果有6个学科,转发器应重复6次。

    <asp:Repeater ID="rptDiscipline" runat="server" OnItemDataBound="rptDiscipline_ItemDataBound">
        <ItemTemplate>
            <h4><%# Eval("Discipline")%></h4>
            <ul>
                <asp:Repeater runat="server" ID="InnerRepeater" >
                    <ItemTemplate>
                        <li>
                            <asp:Label runat="server" ID="lbl" />
                        </li>
                    </ItemTemplate>
                </asp:Repeater>
            </ul>
        </ItemTemplate>
    </asp:Repeater>

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{    

    Repeater inner= (Repeater) e.Item.FindControl("InnerRepeater");

    //You want to bind all the data related to this discipline
    DataRowView drView = (DataRowView) e.Item.DataItem;
    string discipline= drView["Discipline"] as string;

    //filter your total data with ones that match the discipline

    inner.DataSource = //data bind the filtered list here
    inner.DataBind();
}