This should be relatively easy. I do not know why I am struggling with it, but Google cannot help me find an example of what I want to do.
I am building a navigation/menu out a simple nested structure of ULs with LIs. The parent object that is placed on the page is called NavController. It has a collection of NavItems.
So I pretty much let the NavController handle building the base UI, creating the CSS, and JavaScript. It also creates the base UL for the top most level of LIs. From my research and understanding the UI creation should be done in the CreateChildControls method.
Here is my code:
protected override void CreateChildControls()
{
Controls.Clear();
this.Page.RegisterClientJavaScript("~/Resources/Script/SideNav.js");
_ClientObject = this.GetClientJavaScriptObject("SideNav", this.ClientID);
Controls.Add(_BaseContainer);
HtmlGenericControl innerContents = this.BuildBaseContainer();
this.BuildList(innerContents);
_ClientObject.AddParameter("BaseContainerID", _BaseContainer.ClientID, true);
_ClientObject.AddParameter("ImgId", _SideBarTabImg.ClientID, true);
_ClientObject.AddParameter("SideBarContentsId", _SideBarContents.ClientID, true);
base.CreateChildControls();
}
The BuildList method actually builds the top level LIs. I am unsure how this method is called, but I can see that it is. Inside the BuildList function I add to the innerContents's Controls collection the NavItem objects.
First off, is this correct? Placing another custom server control inside of of a UL (with the caveat that the custom control is basically rendering an LI; more on this later)?
The CreateChildControls is never being called for the NavItem. After looking around on the Internet it seemed like it was because I was never calling EnsureChildControls. This confuses me because It will only fire when the ChildControlsCreated property is false. Once it is run this property becomes true. If I have a Text and Href on the NavItem and EnsureChildControls is called when either of them are set then how will the other's value be placed into any sub control?
Just to clog up some screen space here is the code that I have so far for the NavItem:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace AthletesCafe.Web.WebControls.SideNav
{
[ToolboxData("<{0}:NavItem runat=server></{0}:NavItem>")]
public class NavItem : ExtendedWebControl
{
private string _Text;
private string _Value;
private IList<NavItem> _ChildItems = new List<NavItem>();
private HtmlGenericControl _ListItem = new HtmlGenericControl("LI");
private HtmlAnchor _Link = new HtmlAnchor();
private HtmlGenericControl _SubList = new HtmlGenericControl("UL");
public string Text
{
get
{
EnsureChildControls();
return _Text;
}
set
{
EnsureChildControls();
_Text = value;
_Link.InnerText = _Text;
}
}
public string Value
{
get
{
EnsureChildControls();
return _Value;
}
set
{
EnsureChildControls();
_Value = value;
_Link.HRef = _Value;
}
}
protected override void CreateChildControls()
{
Controls.Clear();
Controls.Add(_ListItem);
_ListItem.Controls.Add(_Link);
base.CreateChildControls();
}
public NavItem AddChildItem(string text, string url)
{
EnsureChildControls();
NavItem newItem = new NavItem();
newItem.Text = text;
newItem.Value = url;
_ChildItems.Add(newItem);
this.BuildSubList();
return newItem;
}
private void BuildSubList()
{
_SubList.Controls.Clear();
if (_ChildItems.Count > 0)
{
if (!_ListItem.Controls.Contains(_SubList))
_ListItem.Controls.Add(_SubList);
foreach (NavItem item in _ChildItems)
_SubList.Controls.Add(item);
}
}
protected override void Render(HtmlTextWriter writer)
{
RenderContents(writer);
}
protected override void RenderContents(HtmlTextWriter writer)
{
_ListItem.RenderControl(writer);
//base.RenderContents(writer);
}
public override string ToString()
{
EnsureChildControls();
return _Text + " - " + _Value;
}
}
}
I don't understand why I can't just set the value and text in their public properties and then use some method or manner to place it into the controls before render.
Please, please some point me to the correct way to do this. I have a bunch of these little controls that I need to make that basically do this same approach. I'm going to start a rudimentary toolbar soon and this information would help!
EDIT - Placing in code that shows the list building for clarification:
HtmlGenericControl list = new HtmlGenericControl("UL");
innerContents.Controls.Add(list);
foreach (NavItem item in _Items)
{
list.Controls.Add(item);
}