Visual Studio .NET - nested repeaters

Asked By david stevenson on 24-Aug-06 08:33 AM
I want to be able to write out my navigation using repeaters to generate a <ul> list. eg
<ul>
<li> item 1 </li>
<li> item 2 
<ul>
<li>item 2-1 </li>
<li>item 2-2 </li>
<li>item 2-3 </li>
</ul>
</li>
<li>item 3 </li>
</ul>
Only problem is that when the list is generated if a main item contains no sub-items it still writes out the <ul> and </ul> I have defined in the header and footer of my nested repeater and shows an empty drop down menu in my nav. I have tried to get round this but no luck as yet. OnLoad I run this function to populate the repeater with content.
Sub PopulateMenu()
        Const connectionString As String = "SERVER=localhost;DATABASE=db;Integrated Security=true"
        Dim con As New SqlClient.SqlConnection(connectionString)
        Dim dadCats As New SqlClient.SqlDataAdapter("SELECT tNav.[Nav1ID], tNav.Title, tNav.URL FROM tblNav1 AS tNav ORDER BY tNav.SequenceID", con)
        Dim dadSubCats As New SqlClient.SqlDataAdapter("SELECT tNav.[Nav1ID], tNav.[Nav2ID], tNav.Title, tNav.URL FROM tblNav2 AS tNav ORDER BY tNav.SequenceID", con)
        Dim dst As New DataSet()
        dadCats.Fill(dst, "Sections")
        dadSubCats.Fill(dst, "Categories")
        dst.Relations.Add("Children", _
        dst.Tables("Sections").Columns("Nav1ID"), _
        dst.Tables("Categories").Columns("Nav1ID"))
        parentRepeater.DataSource = dst.Tables("Sections")
        parentRepeater.DataBind()
    End Sub
This works fine, but to try and remove the extra <ul> </ul> from being generated I used
Protected Sub parentRepeater_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles parentRepeater.ItemDataBound
        Dim item As RepeaterItem = e.Item
        If item.ItemType = ListItemType.Item Or item.ItemType = ListItemType.AlternatingItem Then
            Dim childRepeater As Repeater = item.FindControl("childRepeater")
            Dim drv As DataRowView = item.DataItem
            childRepeater.DataSource = drv.CreateChildView("parentRepeater")
            childRepeater.DataBind()
        End If
    End Sub
This is where the error is I get the message 
"The relation is not parented to the table to which this DataView points." 
Any Ideas???

Using the Container DataItem as DataRowView) Row

Asked By Chandu . on 24-Aug-06 08:54 AM
Hi,
Change the Item Template of the  Parent Repeater i.e. UL as follows;
[CODE]
<ul <%# if ((Container.DataItem as DataRowView).Row.GetChildRows().Count == 0) Response.Write("style=\"display:none\"");%>>
--YOU CHILD LI REPEATER --
</ul>
[/CODE]
Let me know for any issues!

Dont think that would work

Asked By david stevenson on 24-Aug-06 09:01 AM
Thank you for your help but that would hide the main nav item if it contained no sub items, I want the main nav item to remain visible but do not want the child repeater to write out its header and footer. When no child items exist I still get the <ul> and </ul> written out which creates an empty drop down in my nav. Heres the presentation code as well
<ul>
<asp:repeater id="parentRepeater" runat="server" OnItemDataBound="parentRepeater_ItemDataBound">
<itemtemplate>
		<li><a href='/sections_<%# Container.DataItem("Nav1ID") %>.aspx' class="nav_separator"><%#DataBinder.Eval(Container.DataItem, "Title")%></a>
    		 <asp:repeater id="childRepeater" runat="server">
	            <HeaderTemplate>
	                <ul>
    	        </HeaderTemplate>
	            <itemtemplate>
   		            <li><a href='/categories_<%# Container.DataItem("Nav1ID") %>_<%# Container.DataItem("Nav2ID") %>.aspx'><%# Container.DataItem("Title") %></a></li>
    	        </itemtemplate>
	            <FooterTemplate>
	                </ul>
	            </FooterTemplate>
	        </asp:Repeater> 
		</li>
	</itemtemplate>
</asp:Repeater>
</ul>

Even More Optimizwed Solution

Asked By Chandu . on 24-Aug-06 09:05 AM
Hi,
You can use this one as well. This is better one!
[CODE]
//C#
private void rptrTest_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
	Repeater rptrChild = e.Item.FindControl("childRepeater") as Repeater;
	e.Item.Visible = (rptrChild.Items.Count > 0);
}
//Vb.Net
Protected Sub parentRepeater_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles parentRepeater.ItemDataBound 
	Dim item As RepeaterItem = e.Item 
	If item.ItemType = ListItemType.Item Or item.ItemType = ListItemType.AlternatingItem Then 
		Dim childRepeater As Repeater = item.FindControl("childRepeater") 
		Dim drv As DataRowView = item.DataItem 
		If childRepeater.Items.Count = 0 Then
			item.Visble = 
		End If
	End If 
End Sub
[/CODE]
The changes you need to make are, Bind the Child repeater normally i.e. using the GetChildRows of the Current Row of the Parent Repeater DataItem.
Not sure about the syntatic correctness of the code in VB as I have never worked in VB.
But the Logic should work!
does not work
Asked By david stevenson on 24-Aug-06 09:14 AM
Says item.visible is not a member of repeater
Move the UL and /UL to the Parent Repeater
Asked By Chandu . on 24-Aug-06 09:21 AM
Hi Dave,
Sorry for getting your post wrong!
You can move the <ul> and the <ul/> to the ItemTemplate of the Parent Repeater and wrap the child repeater between these two tags.
Now you can use the code given in my first post to display or hide the <ul> and </ul>
Hope its clear!
still not there
Asked By david stevenson on 25-Aug-06 07:04 AM
Tried this all day yesterday found loads of people with the same problem but no solution.
The solution you gave would not only hide the drop down but also the main nav item. I want to be able to add items that have a main nav item but no sub nav item so that does not work.
still not there
Asked By david stevenson on 25-Aug-06 07:05 AM
Tried this all day yesterday found loads of people with the same problem but no solution. 
The solution you gave would not only hide the drop down but also the main nav item. I want to be able to add items that have a main nav item but no sub nav item so that does not work.