C# Nested Repeaters ASP .Net

Nested repeaters are a very common topic in ASP .Net so I thought it would be a good subject to write on, especially considering the number of solutions that exist when you Google “nested repeaters” that offer plug-and-play answers, but don’t actually explain why one approach may be more optimal than another.

The Solution

XML/HTML for your repeaters:

<asp:Repeater runat="server" ID="rptRobotFactories" EnableViewState="false" OnItemDataBound="rptRobotFactories_ItemDataBound">
                        <ItemTemplate>
                            <div id="header">
                                <%# (((System.Data.DataRowView)Container.DataItem)["FACTORYNAME"]) %>
                            </div>
                            <asp:Repeater runat="server" ID="rptRobots" EnableViewState="false">
                                <HeaderTemplate>
                                    <ul>
                                </HeaderTemplate>
                                <ItemTemplate>
                                    <li>
                                        <%# Eval("ROBOTNAME") %>
                                    </li>
                                </ItemTemplate>
                                <FooterTemplate>
                                    </ul></FooterTemplate>
                            </asp:Repeater>
                        </ItemTemplate>
                    </asp:Repeater>

Code-behind to load data into rptRobotFactories:

//don't forget these guys. save the practice on your typing, finger joints will thank you later =)
using System.Data;
using System.Data.SqlClient;

//a few more variables than necessary were used for code readability. feel free to condense.
//call this function on page load. don't forget your if not postback check
    private void LoadFactories()
    {
        //don't forget to wrap in your exception handling!

          SqlConnection conn = new SqlConnection(
            ConfigurationManager.ConnectionStrings["RobotDBCon"].ConnectionString);

        SqlDataAdapter da = new SqlDataAdapter();
        SqlCommand cmd = new SqlCommand("SP_GET_ROBOTS_IN_FACTORIES", conn);

        cmd.CommandType = CommandType.StoredProcedure;
        //generally you'd probably have some parameters here

        da.SelectCommand = cmd;

        DataTable dtRobots = new DataTable("robots"); //first we get the robots
        
        da.Fill(dtRobots); //notice there's only one SP call and one datatable filled

//this might seem strange using a string array for columns, but the alternative is not as clean IMO
        string[] cols = new string[1]; //if you're uncomfortable using string as primary key add another column and use ID
        cols[0] = "FACTORYNAME";

//these next two lines are the magic makers
        DataTable dtRobotFactories = dtRobots.DefaultView.ToTable("robotfactories", true, cols).Clone();

        dtRobots.DefaultView.ToTable("robotfactories", true, cols).AsEnumerable().Distinct().CopyToDataTable(dtRobotFactories, LoadOption.OverwriteChanges);

        DataSet ds = new DataSet();
        ds.Tables.Add(dtRobotFactories);
        ds.Tables.Add(dtRobots);
       ds.Relations.Add("robotsinfactories",
ds.Tables["robotfactories"].Columns["FACTORYNAME"],
ds.Tables["robots"].Columns["FACTORYNAME"],false);
        ds.Relations[0].Nested = true;

        rptSegments.DataSource = ds.Tables["robotfactories"];
        rptSegments.DataBind();

        conn.Close();
    }

Last piece of code is our itemdatabound event of the parent repeater which loads the child data. Alternatively you can put this inline as the datasource property with a one liner but this approach may allow you more flexibility later:

    protected void rptRobotFactories_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
        {
            Repeater rptRobots = (Repeater)e.Item.FindControl("rptRobots");
            rptRobots.DataSource = ((DataRowView)e.Item.DataItem).CreateChildView("robotsinfactories");
            rptRobots.DataBind();
        }
    }

And that’s it! Your result should look something like:

FACTORY1
 *ROBOTA1
 *ROBOTA2
FACTORY2
 *ROBOTB1
 *ROBOTB2

What makes this code different?

The use of data relations is disputable. Rightfully arguable, depending on the scope of your project and the data being returned and formatted, this may be overkill.

Multiple data relations and tables can use excess resources when simple string variables could be pulled from the dataset and the same achieved with only one repeater or listview.

I do not contest this point but keep in a mind, a simple re-usable design pattern can be rapidly applied to many different sets of data, whereas a customized variable or array based solution will likely be specific to your initial implementation, and not easily re-adapted in another page or separate project.

Ultimately, code patterns will improve your code readability and productivity as a developer.

See my article on how to create secure relational databases in sql for more information on why the result should come back in a single stored procedure rather than making multiple calls.

Advertisement

About Ronnie Diaz

Ronnie Diaz is a software engineer and tech consultant. Ronnie started his career in front-end and back-end development for companies in ecommerce, service industries and remote education. This work transitioned from traditional desktop client-server applications through early cloud development. Software included human resource management and service technician workflows, online retail e-commerce and electronic ordering and fulfillment, IVR customer relational systems, and video streaming remote learning SCORM web applications. Hands on server experience and software performance optimization led to creation of a startup business focused on collocated data center services and continued experience with video streaming hardware and software. This led to a career in Amazon Prime Video where Ronnie is currently employed, building software and systems which stream live sports and events for millions of viewers around the world.

Posted on June 16, 2011, in Programming & Development and tagged , , , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: