Up to the plate stepped control adapters. These let you mess with the presentation layer of the control, in this case change a menu from rendering <Table> tags to <li>.
Here's how...
Add a App_Browsers folder to the project, you can do this from the right click menu.
Add in a "Form.browser" file. This is an XML file that tells the ASP system what class to use instead of the menus presentation layer. Here's a sample.
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Menu" adapterType="TDWeb.MenuControlAdapter" />
</controlAdapters>
</browser>
</browsers>
The "TDWeb.MenuControlAdapter" is the Namespace and class name.
namespace TDWeb {
#region Namespace references
using System;
using System.Web.UI;
using System.Web.UI.Adapters;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.Adapters;
#endregion
public class MenuControlAdapter : MenuAdapter {
#region Methods
private bool MenuItemContainsSelectedItem(MenuItem menuItem) {
if ( menuItem.Selected )
return true;
foreach ( MenuItem childItem in menuItem.ChildItems ) {
if ( this.MenuItemContainsSelectedItem(childItem) ) {
return true;
}
}
return false;
}
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
if ( this.Control != null ) {
this.SelectCurrentPage(this.Control.Items);
}
}
protected override void RenderContents(HtmlTextWriter writer) {
if ( this.Control != null ) {
writer.AddAttribute(HtmlTextWriterAttribute.Id,"qm0");
writer.AddAttribute(HtmlTextWriterAttribute.Class,"qmmc");
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
foreach ( MenuItem menuItem in this.Control.Items ) {
this.RenderMenuItem(menuItem, writer, 0, true);
}
writer.RenderEndTag();
}
}
private bool RenderMenuItem(MenuItem menuItem, HtmlTextWriter writer, int level, bool withArrows) {
bool selected = this.MenuItemContainsSelectedItem(menuItem);
if ( this.Control.StaticDisplayLevels >= level ) {
// Render each item as a
//writer.RenderBeginTag(HtmlTextWriterTag.Li);
writer.Write(@" if (menuItem.Selected)
{
writer.Write(@" class=""selectedmenuitem"" ");
//writer.AddAttribute(HtmlTextWriterAttribute.Class, "selectedmenuitem");
}
writer.Write(@">");
// Current item should be styled with "selected" class ...
//if ( selected )
// writer.AddAttribute(HtmlTextWriterAttribute.Class, @"qmparent");
// If a description was specified, add it as a tooltip ("title" attribute) ...
if ( menuItem.ToolTip != string.Empty )
writer.AddAttribute(HtmlTextWriterAttribute.Title, menuItem.ToolTip);
// Render the "href" attribute ...
//if ( !menuItem.Selected )
writer.AddAttribute(HtmlTextWriterAttribute.Href, menuItem.NavigateUrl);
//writer.AddAttribute(HtmlTextWriterAttribute.Class, "selectedmenuitem");
//// Render the "A" element ...
//if (level == 0)
//{
// writer.AddAttribute(HtmlTextWriterAttribute.Class, "qmparent");
//}
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.WriteEncodedText(menuItem.Text);
writer.RenderEndTag();
//if ( withArrows )
// writer.WriteEncodedText(@" | ");
// Now render any child items ...
if ( this.Control.StaticDisplayLevels > level ) {
if (menuItem.ChildItems.Count > 0 ) {
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
foreach ( MenuItem childItem in menuItem.ChildItems ) {
this.RenderMenuItem(childItem, writer, level + 1, false);
}
writer.RenderEndTag();
}
}
// Close the
writer.Write(@"");
//writer.RenderEndTag();
}
return menuItem.Selected;
}
private void SelectCurrentPage(MenuItemCollection menuItems) {
Uri rawUrl = new Uri(this.Control.Page.Request.Url, this.Control.Page.Request.RawUrl);
this.SelectCurrentPage(menuItems, rawUrl);
}
private void SelectCurrentPage(MenuItemCollection menuItems, Uri rawUrl) {
foreach ( MenuItem menuItem in menuItems ) {
string navigateUrl = this.Control.ResolveUrl(menuItem.NavigateUrl);
Uri targetUrl = new Uri(rawUrl, navigateUrl);
menuItem.Selected = string.IsNullOrEmpty(menuItem.NavigateUrl = rawUrl.MakeRelativeUri(targetUrl).ToString());
this.SelectCurrentPage(menuItem.ChildItems, rawUrl);
}
}
#endregion
}
}