the good news is that i muddled and fiddled until something started working. :) the bad news is that i probably did this in a very that-is-SO-not-even-right way, but since i don't have anything else to go off of, my way is all i've got. if someone else wanted the functionality more than pretty code, here is my app_code/adapters/treeview.cs code in its entirety. hopefully it will spark something for someone else, who will post back a better method than this. (hint hint)
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CSSFriendly
{
public class TreeViewAdapter : System.Web.UI.WebControls.Adapters.HierarchicalDataBoundControlAdapter
{
public TreeNode activeNode;
public bool isActivePath = false;
public TreeViewAdapter()
{
//
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
RegisterScripts();
}
private void RegisterScripts()
{
Utility.RegisterScripts(Page);
Page.ClientScript.RegisterClientScriptInclude(GetType(), GetType().ToString(), Page.ResolveUrl("~/includes/adapters/treeview.js"));
}
protected override void RenderBeginTag(HtmlTextWriter writer)
{
if ((Control != null) && (Control.Attributes["CssSelectorClass"] != null) && (Control.Attributes["CssSelectorClass"].Length > 0))
{
writer.WriteLine();
writer.WriteBeginTag("div");
writer.WriteAttribute("class", Control.Attributes["CssSelectorClass"]);
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
}
writer.WriteLine();
writer.WriteBeginTag("div");
writer.WriteAttribute("class", Control.Attributes["CssSelectorClass"] + "-inside");
writer.Write(HtmlTextWriter.TagRightChar);
}
protected override void RenderEndTag(HtmlTextWriter writer)
{
writer.WriteEndTag("div");
if ((Control != null) && (Control.Attributes["CssSelectorClass"] != null) && (Control.Attributes["CssSelectorClass"].Length > 0))
{
writer.Indent--;
writer.WriteLine();
writer.WriteEndTag("div");
}
writer.WriteLine();
}
protected override void RenderContents(HtmlTextWriter writer)
{
TreeView treeView = Control as TreeView;
if (treeView != null)
{
AssureAllNodesAreBuilt(treeView);
activeNode = treeView.SelectedNode;
writer.Indent++;
BuildItems(treeView.Nodes, true, true, writer);
writer.Indent--;
writer.WriteLine();
}
}
private void BuildItems(TreeNodeCollection items, bool isRoot, bool isExpanded, HtmlTextWriter writer)
{
if (items.Count > 0)
{
writer.WriteLine();
writer.WriteBeginTag("ol");
if (!isExpanded)
{
writer.WriteAttribute("class", "menu-hide");
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
foreach (TreeNode item in items)
{
BuildItem(item, writer);
}
writer.Indent--;
writer.WriteLine();
writer.WriteEndTag("ol");
}
}
private void BuildItem(TreeNode item, HtmlTextWriter writer)
{
TreeView treeView = Control as TreeView;
if ((treeView != null) && (item != null) && (writer != null))
{
isActivePath = false;
if (IsActivePath(item)) // cj
item.Expand();
#region [start tags]
writer.WriteLine();
writer.WriteBeginTag("li");
writer.WriteAttribute("class", GetNodeClass(item, isActivePath)); // cj
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
writer.WriteLine();
#endregion
#region [expand button]
if (item.ChildNodes.Count > 0)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("class", ((item.Expanded == true) ? "menu-collapse" : "menu-expand"));
writer.WriteAttribute("onclick", "ExpandCollapse__AspNetTreeView(this)");
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(" ");
writer.WriteEndTag("span");
writer.WriteLine();
}
#endregion
if (item.NavigateUrl.Length > 0)
{
#region [create link]
writer.WriteBeginTag("a");
if (item.Parent == null)
writer.WriteAttribute("class", "chapter");
writer.WriteAttribute("href", Page.ResolveUrl(item.NavigateUrl));
if (item.Target.Length > 0)
{
writer.WriteAttribute("target", item.Target);
}
if (item.ToolTip.Length > 0)
{
writer.WriteAttribute("title", item.ToolTip);
}
else if (treeView.ToolTip.Length > 0)
{
writer.WriteAttribute("title", treeView.ToolTip);
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
writer.WriteLine();
#endregion
}
else
{
#region [parent - no link]
writer.WriteBeginTag("span");
if (item.ChildNodes.Count > 0)
{
writer.WriteAttribute("class", "menu-clickable");
writer.WriteAttribute("onclick", "ExpandCollapse__AspNetTreeView(this.parentNode.getElementsByTagName('span')[0])");
}
else
{
writer.WriteAttribute("class", "menu-nothing");
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
writer.WriteLine();
#endregion
}
#region [set child graphic]
string imgSrc = GetImageSrc(treeView, item);
if (imgSrc.Length > 0)
{
writer.WriteBeginTag("img");
writer.WriteAttribute("src", Page.ResolveUrl(imgSrc));
writer.WriteAttribute("alt", item.ToolTip.Length > 0 ? item.ToolTip : (treeView.ToolTip.Length > 0 ? treeView.ToolTip : item.Text));
writer.Write(HtmlTextWriter.SelfClosingTagEnd);
}
#endregion
writer.Write(item.Text);
#region [end tags and insert children]
if (item.NavigateUrl.Length > 0)
{
writer.Indent--;
writer.WriteLine();
writer.WriteEndTag("a");
}
else
{
writer.Indent--;
writer.WriteLine();
writer.WriteEndTag("span");
}
if ((item.ChildNodes != null) && (item.ChildNodes.Count > 0))
{
BuildItems(item.ChildNodes, false, (item.Expanded == true), writer);
}
writer.Indent--;
writer.WriteLine();
writer.WriteEndTag("li");
#endregion
}
}
private string GetNodeClass(TreeNode item, bool isActive)
{
string value = Control.Attributes["CssSelectorClass"] + "-leaf";
if (item != null)
{
if (item.Depth == 0)
{
if (item.ChildNodes.Count > 0)
{
value = Control.Attributes["CssSelectorClass"] + "-root " + Control.Attributes["CssSelectorClass"] + "-parent";
}
else
{
value = Control.Attributes["CssSelectorClass"] + "-root " + Control.Attributes["CssSelectorClass"] + "-leaf";
}
}
else if (item.ChildNodes.Count > 0)
{
value = Control.Attributes["CssSelectorClass"] + "-parent";
}
}
if (isActive) // cj
{
TreeView treeView = Control as TreeView; // find me - this is kind of redundant
value = treeView.SelectedNodeStyle.CssClass + " " + value;
}
return value;
}
private string GetImageSrc(TreeView treeView, TreeNode item)
{
string imgSrc = "";
if ((treeView != null) && (item != null))
{
imgSrc = item.ImageUrl;
if (imgSrc.Length == 0)
{
if (item.Depth == 0)
{
if ((treeView.RootNodeStyle != null) && (treeView.RootNodeStyle.ImageUrl.Length > 0))
{
imgSrc = treeView.RootNodeStyle.ImageUrl;
}
}
else
{
if (item.ChildNodes.Count == 0)
{
if ((treeView.LeafNodeStyle != null) && (treeView.LeafNodeStyle.ImageUrl.Length > 0))
{
imgSrc = treeView.LeafNodeStyle.ImageUrl;
}
}
else if ((treeView.ParentNodeStyle != null) && (treeView.ParentNodeStyle.ImageUrl.Length > 0))
{
imgSrc = treeView.ParentNodeStyle.ImageUrl;
}
}
}
if ((imgSrc.Length == 0) && (treeView.LevelStyles != null) && (treeView.LevelStyles.Count > item.Depth))
{
if (treeView.LevelStyles[item.Depth].ImageUrl.Length > 0)
{
imgSrc = treeView.LevelStyles[item.Depth].ImageUrl;
}
}
}
return imgSrc;
}
private void AssureAllNodesAreBuilt(TreeView treeView)
{
if (treeView != null)
{
int currentDepth = treeView.ExpandDepth;
treeView.ExpandDepth = -1;
treeView.ExpandAll();
treeView.ExpandDepth = currentDepth;
if (treeView.ExpandDepth > -1)
{
treeView.CollapseAll();
ExpandToDepth(treeView.Nodes, treeView.ExpandDepth);
}
}
}
static public void ExpandToDepth(TreeNodeCollection nodes, int expandDepth)
{
foreach (TreeNode node in nodes)
{
if (node.Depth < expandDepth)
{
node.Expand();
ExpandToDepth(node.ChildNodes, expandDepth);
}
}
}
public bool IsActivePath(TreeNode node) // cj
{
foreach (TreeNode child in node.ChildNodes)
{
IsActivePath(child);
}
if (node.Equals(activeNode))
isActivePath = true;
return isActivePath;
}
}
}
[note: i didn't take out any of my personal comments since most of the places i put them are where i changed code for this "active" project and they might help you find most of the different lines.]