Web development with Asp.net is very fast. We have drag and drop controls with out of the box functionality. This concept of prebuild controls is of huge advantage when it comes to rapid application development, saving us allot of time ... but there is one major drawback. We are normally limited to what the controls offer in: rendering, functionality, etc.
Microsoft controls normally render table based designs, which are very difficult to style. If you want to override this you can achieve it using CssFriendlyControlAdapters. It's the same case for the TreeView Control but the table based rendering is probably not the thing that bothers me the most!
In my opinion Microsoft did a poor job with the TreeView control when talking about style. Normally Asp.net controls have Style and CssClass properties to set visual appearance. It is not the case for a TreeNode.
I know there is a way to style a TreeNode, but only on a general level like: NodeStyle, LeafNodeStyle, HoverNodeStyle, RootNodeStyle. I wish there was a bit more flexibility. Styling a TreeNode individually is totally essential as we may want to adjust color based on some values.
There an event called TreeNodePopulate which can be handled to insert some custom code in order to achieve styling.
protected void tv_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
if (e.Node.Value == "something you expect")
{
e.Node.Text = "<div style='color:blue'>" + e.Node.Text + "</div>";
}
}
The only problem here is that this event is only fired when we are databinding the TreeView. In practice we normally create our TreeView dynamically using the Nodes/ChildNodes.Add() properites.
The obvious solution in this case is to extend the TreeNode class, add a property called CssClass which will be rendered accordingly. Due to the stateless nature of the web, settings like our CssClass string have to be saved somewhere. The usual place to save such information is the ViewState. Sadly the ViewState object isn't accesible from the TreeNode class, therefore we need to override the LoadViewState and SaveViewState methods.
Here's the CustomTreeNode class which lets us set the CssClass individually.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
/// <summary>
/// This is an extended TreeNode, to allow styling
/// </summary>
public class CustomTreeNode : System.Web.UI.WebControls.TreeNode
{
public CustomTreeNode()
: base()
{
}
public CustomTreeNode(string Text)
: base(Text)
{
}
private string _CssClass = null;
public string CssClass
{
get
{
if (_CssClass != null)
return _CssClass;
else
return String.Empty;
}
set
{ _CssClass = value; }
}
protected override void LoadViewState(Object savedState)
{
if (savedState != null)
{
object[] myState = (object[])savedState;
if (myState[0] != null)
base.LoadViewState(myState[0]);
if (myState[1] != null)
CssClass = (String)myState[1];
}
}
protected override Object SaveViewState()
{
object baseState = base.SaveViewState();
object[] allStates = new object[3];
allStates[0] = baseState;
allStates[1] = CssClass;
return allStates;
}
protected override void RenderPreText(HtmlTextWriter writer)
{
writer.AddAttribute("class", CssClass);
base.RenderPreText(writer);
}
}