Posts tagged: Treeview

Jun 23 2009

How to fake a TreeNodeCollection subclass in .NET

If you’ve ever had reason to try to extend the standard Microsoft web TreeView control, you will have no doubt noticed that MS was quite unkind to you and sealed (or declared NotInheritable for you VB.NET types) the System.Web.UI.WebControls.TreeNodeCollection class.

The problem arises when you want to overload the default behavior that is implemented by the TreeNodeCollection class. For example, when a node was added to my TreeView class (via the TreeView.Nodes.add method), I needed to be able to analyze it for the ultimate purpose of my subclass.

However, this was not possible because the TreeNodeCollection class is sealed, so I wasn’t able to inherit from it and overload the add method behavior as I should have been able to do.

There are always possibilities.

Anyone who knows me knows I don’t give up easily (if ever), and I eventually plowed through many false starts but hit upon a solution.

I decided to wrap the underlying TreeNodeCollection class with my own, and overload the Nodes property on the TreeView class, and the ChildNodes property on the TreeNode class.

The Wrapper.

Here’s what the wrapper looks like:
[vb language=".net"]

Public Class MyTreeNodeCollection

Private mtvwChildNodes As System.Web.UI.WebControls.TreeNodeCollection
Private mMyTreeViewOwner As IMyNodeContainer

Public Sub New(ByVal Owner As IMyNodeContainer, _
ByVal TreeViewChildren As System.Web.UI.WebControls.TreeNodeCollection)
mtvwChildNodes = TreeViewChildren
mMyTreeViewOwner = Owner
End Sub

Public Sub Add(ByVal child As MyTreeNode)
mtvwChildNodes.Add(CType(child, System.Web.UI.WebControls.TreeNode))
mMyTreeViewOwner.RegisterNodeForLookup(child)
End Sub
End Class
[/vb]

As you can see, the constructor takes the real, underlying TreeNodeCollection to pass all node to prior to being “registered” (analyzed). It also takes something that implements the IMyNodeContainer interface.

The IMyNodeContainer interface.

I had to implement this because I wanted to be able to use this wrapper class for both TreeView and TreeNode objects, but the signature of their properties is different - TreeView.Nodes and TreeNode.ChildNodes, respectively. So I opted for the interface to keep things clean.

Here’s what the interface looks like:

[vb language=".net"]
Public Interface IMyNodeContainer

Sub RegisterNodeForLookup(ByVal node As MyTreeNode)
ReadOnly Property Nodes() As MyTreeNodeCollection

End Interface
[/vb]

Wrapping things up.

This is where the magic happens.

To put the wrapper (MyTreeNodeCollection) in place, I overload the collection getting properties in the base class - TreeView.Nodes and TreeNode.ChildNodes, respectively, like so:

[vb language=".net"]
Public Overloads ReadOnly Property Nodes() As MyTreeNodeCollection Implements IMyNodeContainer.Nodes
Get
Return mNodeCollection
End Get
End Property
[/vb]

So, for those of you playing along at home, when the developer calls .Nodes on an instance of MyTreeView class, an instance of MyTreeNodeCollection is returned and the resulting add method in performed on the underlying TreeNodeCollection, thusly:

[vb language=".net"]
Public Sub Add(ByVal child As MyTreeNode)
mtvwChildNodes.Add(CType(child, System.Web.UI.WebControls.TreeNode))
mMyTreeViewOwner.RegisterNodeForLookup(child)
End Sub
[/vb]

You can see why I had to use the IMyNodeContainer interface here. The RegisterNodeForLookup performs the functionality I was originally trying to subclass the TreeNodeCollection for.

Blog Traffic Exchange Related Posts
Jun 16 2009

IE7 WebControl TreeView line gap in quirks mode.

I’ve been writing a subclass of the MS Webcontrol.TreeView control for one of our Web Applications at work. I figured this would be a fairly easy task, since I only needed to extended it with a few properties. It turns out that I was caught on a nit-picky annoyance in the TreeView control itself.

The TreeView control renders verticals lines with gaps.

Here’s a screen cap of the problem.

ie7-webcontrol-treeview-line-gap-in-quirks-mode_treeview-line-break

As you can see, the TreeView control renders the vertical line with a gap, or break (looks like a dashed line!). It didn’t matter how I loaded the data - dynamic/runtime/design time - I get the same gap no matter what!

I was able to see that it was not a problem in IE 6 or less, but what good is that? Well, it turns out that it was a bit of a clue because starting with version 5, IE didn’t render things correctly per the CSS boxing specification. This was fixed in IE 7, but to provide backwards compatibility, Microsoft carried this busted form of rendering forward in IE 6 as QuirksMode. The line gap problem only occurs in strict mode (default for IE 7 and 8, as well as firefox). I could make the line gap go away by forcing the browser into QuirksMode (by adding a comment, ex:

< ! - - QUIRK! - - >

to the very top of the HTML file), but I was writing a web control and would not always have the luxury of controlling my container.

I needed to find a long term solution to this problem.

Next, I looked at the HTML source of the rendered page, and saw this:

[html]
<table cellpadding="0" cellspacing="0" style="border-width:0;">
<tr>
<td>
<div style="width:20px;height:1px">
<img src="/TreeviewControlTest/WebResource.axd?d=OYmDnVppVECKIpxOWC8o8Y7DO6QwB2J3EY4s4RR8zAU1&amp;t=633765128008804061" alt="">
</div>
</td>
<td>
<img src="/TreeviewControlTest/WebResource.axd?d=OYmDnVppVECKIpxOWC8o8UGy0bLoCc8gOB1oQm6Pzj81&amp;t=633765128008804061" alt="">
</td>
<td class="TreeView1_WebTree_1" style="white-space:nowrap;">
<a class="TreeView1_WebTree_0" href="javascript:__doPostBack(’TreeView1$WebTree’,'Root//Tree’)" onclick="TreeView_SelectNode(TreeView1_WebTree_Data, this,’TreeView1_WebTreet6′);" id="TreeView1_WebTreet6" name="TreeView1_WebTreet6">Tree</a>
</td>
</tr>
</table>
[/html]

Each node is rendered as a table, with the vertical line and expand/collapse icons being in their own table cell and wrapped in a div. The problem was the style applied to the outer div - style=”width:20px;height:1px“.

That 1px height was causing the vertical line image to be compressed, but where did it come from?

Reflecting on System.Web.UI.WebControls.TreeNode

I spent almost an hour delving into the various (and copious!) style properties for the tree and its nodes, looking for where this height setting was generating from. I couldn’t find it! I eventually opened the System.Web.UI.WebControls.dll in Reflector to see what the render code for the node was doing:

ie7-webcontrol-treeview-line-gap-in-quirks-mode_treeview-reflector

Well, once I saw that the code was hard-wired to render this CSS style, I was done. Or was I?

!important

Well, it wasn’t going to be as easy as setting the style in the code behind, but I could override the style in my own class.

The trick is to define, and apply the following CSS class:

[css]
<style type="text/css">
.MyTreeView TD Div
{
height: 20px!important;
}
</style>
[/css]

The !important CSS directive overrides the style applied in the System.Web.UI.WebControls.TreeNode render method.

ie7-webcontrol-treeview-line-gap-in-quirks-mode_treeview-no-line-break

Again, just as with the QuirksMode comment above, I was able to add the CSS style to the page and voila - problem solved. But this still wasn’t good enough. I needed this to work out of the box for any consumers of my control.

The ultimate answer was to override the RenderBeginTag of the TreeView control, and render this style before the control itself:

[vb language=".net"]

Public Overrides Sub RenderBeginTag(ByVal writer As System.Web.UI.HtmlTextWriter)
‘/////////////////////////////////////////////////////////////////////////////////////////
‘/// This is a total hack to get around some Microsoft BS which hardwires
‘/// a style attribute on the node div to set the height = 1px!
‘///
‘/// This renders a css override to force the div to the proper height
‘/////////
Me.CssClass = String.Concat(Me.CssClass, " MyTreeView")
writer.WriteBeginTag(HtmlTextWriterTag.Style.ToString)
writer.WriteAttribute(HtmlTextWriterAttribute.Type.ToString, "text/css")
writer.WriteLine(HtmlTextWriter.TagRightChar)
writer.Write(".MyTreeView TD Div ")
writer.WriteLine("{ height: 20px!important; }")
writer.WriteEndTag(HtmlTextWriterTag.Style.ToString)
writer.WriteLine()
‘//////////////////////////////////////////////////

‘/// Render the Standard Begin Tag
MyBase.RenderBeginTag(writer)
End Sub
[/vb]

Blog Traffic Exchange Related Posts Blog Traffic Exchange Related Websites
  • Search Engine Optimization Seo Search Engine Optimization (SEO) in Dubai Like other business homes Dubai conjointly have internet solutions firms that provide complete range solutions of internet development are operating on new trends and selling ways for on-line businesses. Dubai is the business hub for the globe trade. It’s the time of on-line businesses.......
  • Important Reasons For Submitting Articles Article directories are important to many web site owners all over the world. Many of them submit large numbers of articles to article directories on regular basis. No matter what type of business you have, you probably get a lot of things to share with your readers. Writing and submitting......
  • Top Best 100 Incredibly Useful & Free Mac Apps [/caption] Everyone loves free applications. One of the greatest things about Macs is the wealth of extremely talented developers that are willing to share their amazing creations without asking for a single cent. We’ve compiled an enormous list of 100 amazing free Mac applications that you can download and start......
  • Internet Marketing Needs a Makeover? Let me start by saying: and a Major One at that! Last time I checked:  we are in the 21st century, so how come Internet marketers are still stuck in the yesteryears? Allow me to count the ways:     HTML Your Basic HTML is still the foundation and serves......
  • What Does It Take To Become A Search Engine Optimization Specialist? Search Engine Optimization or SEO has become quite a buzzword on the Internet for a number of years now. It seems that people claiming to be an SEO expert are a dime a dozen but many of these people only have a cursory knowledge on the matter and are only......