Recursive ASP user control
asp.net, c#, sharepoint-2007, user-controls
Solution
You need to Load the control from code instead of the markup. That is due to how the asp.net compiler creates the assemblies from your mark up.
I made the following changes to load the control from the codebehind. I had to change the databinding as well by changing the # to = (and have properties on the control).
Control MenuButton.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MenuButton.ascx.cs" Inherits="WebApplication1.MenuButton" %>
<li id="Li1" runat="server">
<% if (Children.Count == 0)
{ %>
<a href="<%= Url %>"><%= Description %></a>
<% }
else
{
%>
<a href="<%= Url %>" class="dropdown-toggle" data-toggle="dropdown">
<%= Description %><b class="caret"></b></a>
<!-- is now a server control -->
<ul class="dropdown-menu multi-level" runat="server" ID="ul1">
<!-- the page_load adds MenuButtons here -->
</ul>
<%
}
%>
</li>
Codebehind MenuButton.ascx.cs
public partial class MenuButton : System.Web.UI.UserControl
{
public String Url { get; set; }
public string Description { get; set; }
public List<MenuItem> Children { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (Children != null)
{
foreach (var menuItem in Children)
{
// Create a button from the ascx file
var but = (MenuButton)LoadControl("/MenuItems/MenuButton.ascx");
// bind!
but.Children = menuItem.Children;
but.Description = menuItem.Description;
but.Url = menuItem.Url;
if (ul1 != null)
{
// add our button
ul1.Controls.Add(but);
}
}
}
}
}
ViewModel
public class MenuItem
{
public List<MenuItem> Children { get; set; }
public String Url { get; set; }
public string Description { get; set; }
}
Problem
I am trying to make a user controls for multi-level menu. I have created first-level control which works. Its iterating with repeater and instantiating my own MenuButton class. Each MenuButton object has children of same type. The question is: How to create MenuButton control inside MenuButton.aspx file? I am using repeater like this ``` <%@ Control ClassName="MenuButton" Language="C#" AutoEventWireup="true" CodeBehind="MenuButton.ascx.cs" Inherits="MenuSolution._12.TEMPLATE.CONTROLTEMPLATES.MenuButton, MenuSolution, Version=1.0.0.0, Culture=neutral, PublicKeyToken=284eb573cd58385d" %> <%@ Register TagPrefix="a" Namespace="MenuSolution._12.TEMPLATE.CONTROLTEMPLATES" Assembly="MenuSolution, Version=1.0.0.0, Culture=neutral, PublicKeyToken=284eb573cd58385d" %> <li runat="server"> <% if (Children.Count == 0) { %> <a href="<%# Url %>"><%# Description %></a> <% } else { %> <a href="<%# Url %>" class="dropdown-toggle" data-toggle="dropdown"> <%# Description %><b class="caret"></b></a> <ul class="dropdown-menu multi-level"> <asp:Repeater ID="repDynamicRows" runat="server"> <ItemTemplate> <a:MenuButton runat="server" id="button" url='<%# DataBinder.Eval(Container.DataItem, "Url") %>' children='<%# DataBinder.Eval(Container.DataItem, "ChildItems") %>' description='<%# DataBinder.Eval(Container.DataItem, "Description") %>' /> </ItemTemplate> </asp:Repeater> </ul> <% } %> </li> ``` and this code does not place MenuButton code inside final HTML. I was trying to register this control like: ``` <%@ Register TagPrefix="a" TagName="MenuButton" Src="~/_controltemplates/MenuButton.ascx" %> ``` But this leads to circural reference. How should i do that?