Displaying hierarchical data is one of the common practices of any application. Although the solution is not complicated but sometimes it can take unexpected turns which needs special attention. In this article we are going to learn how to display hierarchical Repeater controls and deal with the problem when the child Repeater does not have any items to display.

Introduction:

Displaying hierarchical data is one of the common practices of any application. Although the solution is not complicated but sometimes it can take unexpected turns which needs special attention. In this article we are going to learn how to display hierarchical Repeater controls and deal with the problem when the child Repeator does not contain any items.

The Scenario:

The scenario is pretty simple! We like to display nested data from the Northwind database. The nested data will be between the Categories table and the Products table. But there is a catch! We must only use the Repeater control and other HTML controls. This means we cannot use any other ASP.NET web server control. This seems little odd but there is a valid reason behind this scenario.

Rendering User Control Using Ajax:

Although we will not cover the Ajax or User Control in this article but you might find some insights of the application to be helpful. In the actual application the Repeater is placed inside a User Control which should be rendered using an Ajax call. In order to render a User Control it must be converted to HTML. ASP.NET web server controls require that all controls must be placed inside the form element with runat equals to server. Since, user control does not contain a form element the rendering of web server control will fail. For that reason we only used the Repeater control and plain HTML controls. Repeater will go through the HTML conversion since it renders as plain text.

Populating the Repeator Control:   

The first task is to populate the Repeater control. Check out the implementation shown below:

  private void BindData()
        {
            using (NorthwindDataContext northwind = new NorthwindDataContext())
            {
                repCategories.DataSource = (from c in northwind.Categories
                                           select c).OrderByDescending(o => o.CategoryName);
                repCategories.DataBind();                                           
            }
        }


We are using LINQ to SQL as data access layer but you are free to use any DAL you like.

Now, here is the HTML code for the Repeater control:

<asp:Repeater ID="repCategories" runat="server">
    
    <ItemTemplate>
    <li>
    
    <div style="background-color:Yellow;">
    <%# Eval("CategoryName") %>
    </div>
   
    </li>
    
    <asp:Repeater ID="repProducts" DataSource='<%# Eval(“Products”) %>' runat="server">
    
    <ItemTemplate>
    <br />
    
    
    
    <%# Eval("ProductName") %>
    <%# Eval("UnitPrice") %>
    
    </ItemTemplate>
    
    </asp:Repeater>
    
    
    </ItemTemplate>
    
    
    </asp:Repeater>

    
As, you can see the outer Repeater “repCategories” is the parent element and displays the “Categories” on the page. The inner Repeater “repProducts” is used to show the products of the particular category.
 



As, you can see in the above screenshot if the category does not have any products then nothing is displayed. To make the user experience better we should display something like “There are no products in this category”.

This task sounds simple but remember we cannot use any web server controls. Let’s see how we can fix this issue.

Implementing the ValidateContainerForItems Method:

The ValidateContainerForItems method will be responsible for checking that if the product collection exists or not. If the product collection exists then simply return the collection. Otherwise, create a new collection and add a dummy product into the collection and then return it. The implementation of the inner Repeater now contains a call to the ValidateContainerForItems method as shown below:

<asp:Repeater ID="repProducts" DataSource='<%# ValidateContainerForItems<WebApplication1.Product>(Eval("Products")) %>' runat="server">

The ValidateContainerForItems method is shown below:

protected IEnumerable<T> ValidateContainerForItems<T>(object container) where T : class
        {
            // if the container has items then return the container!

            var set = container as EntitySet<T>;
            
            if (set.Count == 0)
            {
                NullProduct nullProduct = new NullProduct() { ProductName = "This category does not have any products!" };
                // create an empty list
                set = new EntitySet<T>();
                set.Add(nullProduct as T);
                return set;
            }

            return set;
        }


As, you can see if the container does not contain any elements then a new dummy product called “NullProduct” is added to the collection. The NullProduct contains the message that will be displayed when there are no products in the Product collection.

You can see the effect in the screenshot below:

 

Conclusion:

In this article we learned how to display a custom message when the nested Repeater does not contain any items. There are many different ways of solving this problem and each solution is suited for its own scenario.

Download Sample