Posts tagged: .net

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
  • Progress in Software Development – Scaling New Heights Software development is no less than a revolution in the history, as it has entered each and every profession and industrial field. The demand for variety of software systems is experiencing high times and the credit goes to four different set of individuals. The following discussion will highlight the contribution......
  • Book Review: The Hal Leonard Acoustic Guitar Method The Hal Leonard Acoustic Guitar Method book includes real songs you can hear on the radio to teach a variety of acoustic guitar concepts. Included are songs by Eric Clapton, Robert Johnson, James Taylor, the Indigo Girls, and many others. There are lesson sections on topics such as finger picking,......
  • Why Your SEO Firm Should Be Acquainted With Web Development – Becoming A Successful SEO If you are in the market to hire a search engine optimization (SEO) firm, selecting the right vendor can be a daunting task. In recent years, SEO has gained immense popularity and acceptance as a formidable marketing technique, so it should come as no surprise that SEO firms are popping......
  • Web Site Maintenance Design -- Design To Save Time! It is a smart thing to try to save as much time in construction, and later in maintenance time as you can, so you can free yourself more valuable time building great content.When building a web site, it is important to have a plan to give yourself good direction......
  • Search Engine Friendly Content Management Systems What is a Content Management System? A Content Management System (CMS) is a third party software application which allows web site administrators to add, update or delete content, photos, and documents to their web site in “real time”. Many web sites are modified using these web-based tools as they require......
Jun 09 2009

Arraylist and generics don’t mix with IEnumerable(Of T).GetEnumerator.

The other day I was writing an in-house tool to assist in some upgrades we were performing on client installations. This tool was supposed to perform its operations on a batch of items, and display the results upon completion.

Since processing this batch of items was a lengthy endeavor, I wanted the failure to process one of the items to simply be recorded and allow the processing of the others to continue. Part of the processing of each item was a call to multiple web services, so I would need a way to handle the collection of errors along the way and make them available for their eventual display.

I had what I thought was a clever idea: a private Arraylist of exceptions that occurred during processing.

[vbnet]
Public Class BatchExceptions
Implements ICollection(Of System.Exception)

Private mExceptionlist As ArrayList
.
.
.
End Class
[/vbnet]

That way, I could simply iterate over the list and perform the standard exception handling, like so:

[vbnet]
Dim exc As Exception
For Each exc In BatchExceptions
HandleError(exc)
Next
[/vbnet]

Of course, in order to make use of the “For Each” construct, I had to implement the GetEnumerator of the ICollection interface.

[vbnet]
Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of System.Exception) _
Implements System.Collections.Generic.IEnumerable(Of System.Exception).GetEnumerator
Return (mExceptionlist.GetEnumerator)
End Function
[/vbnet]

Cool. Only one problem:

arraylist-and-generics-dont-mix-when-enumerating-generics_generics-enumerator

That was OK though, because I was using generics after all. The compiler was being helpful and reminding me that I had to specify ‘IEnumerator(Of Exception)’:

arraylist-and-generics-dont-mix-when-enumerating-generics_generics-enumerator2

[vbnet]
Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of System.Exception) _
Implements System.Collections.Generic.IEnumerable(Of System.Exception).GetEnumerator
Return (DirectCast(mExceptionlist.GetEnumerator, IEnumerator(Of Exception)))
End Function
[/vbnet]

Everything compiled fine, but at run-time I got the following RTE:

Unable to cast object of type ‘ArrayListEnumeratorSimple’ to type ‘System.Collections.Generic.IEnumerator`1[System.Exception]‘.

arraylist-and-generics-dont-mix-when-enumerating-generics_generics-enumerator-rte

This was frustrating. It seemed like the compiler failed to warn me of this incompatibility, and simply kicked the can on down the road to the run-time to deal with.

Solution:

Well, I did a little poking around and finally ended up replacing my Arraylist with a list like so:

[vbnet]
private mExceptionlist as System.Collections.Generic.list
[/vbnet]

Well, that did the trick but I can’t say it was as intuitive as it would seem. It makes sense, in hindsight, but why did I have to get some cryptic RTE? Why couldn’t the compiler have picked up on my use of an ArrayList and say, “Hey dummy - use a generic list!”? Still, I have a new trick to toss in my bag for the time I want to implement an enumerator on an Arraylist!

Blog Traffic Exchange Related Posts Blog Traffic Exchange Related Websites
  • MonaVie and Inc. Magazine's 500 A lot of MonaVie distributors seem to tout the fact that Inc. magazine named MonaVie it's #1 choice in Food and Beverage and 18th overall. A few things should be noted about this list: It's a list of privately held companies - You won't see Coca-Cola, Pepsi, ConAgra foods or......
  • Grocery Budget Makeover - I saved $25 At the Grocery Store Today Recently, I've written that we have reviewed our expenses for 2006 and discovered that the cost of nearly everything had risen. I've decided to tackle the grocery budget and have set a new monthly goal for total grocery expenses. Yesterday, I went through and took an inventory of my pantry,......
  • Kiss and Tell: Carmen Shirkey on Her Hero Today's article is written by romance author Carmen Shirkey. Okay, I decided to risk embarrassing Jim and participate in your new Kiss & Tell feature. :) My book, The List, is about a woman who has a ridiculously long list of characteristics she wants in her future boyfriend/husband. That was......
  • Opening my mind to money Tread pointed out something that's going on over at Millionaire Mommy Next Door. MMND said: "For the next 30 days, I'll open my mind to receive increasingly more money. On day one, I'll decide how I'd like to spend $100. On day two, I'll double that amount to $200. Day......
  • The Male And Shopping Perhaps all men would agreewith me that shopping is, in one way or another, a traumatic experience. However, I have found several means on how to make the experience so much better. I have personally found satisfaction in buying items, as long as I follow my guidelines. Planning can save......
Jun 02 2009

Microsoft FxCop doesn’t like Microsoft generated code!

The other day I thought it might be nice to “do the right thing” and give my code a run against Microsoft’s FxCop.

I ran it right out of the box - I didn’t bother making my own rules or changing the defaults. I was bored. Anyway, here’s one of the results that actually made be chuckle once I read it carefully:

Warning, Certainty 90, for DoNotInitializeUnnecessarily
{

Target : #.ctor() (IntrospectionTargetMember)
Location : <735>> (String)
Resolution : “‘MyDocument.New()’ initializes field ‘MyDocument.disposedValue’
of type ‘Boolean’ to false. Remove this initialization
because it will be done automatically by the runtime.”

Help : (String)
Category : Microsoft.Performance (String)
CheckId : CA1805 (String)
RuleFile : Performance Rules (String)
Info : “Do not make initializations that have already been
done by the runtime.”
Created : 3/6/2009 6:58:21 PM (DateTime)
LastSeen : 3/6/2009 8:36:25 PM (DateTime)
Status : Active (MessageStatus)
Fix Category : NonBreaking (FixCategories)

}

The reason for the chuckle was that the code which triggered this violation of the rule was written by the Microsoft IDE! My role in this infraction was really quite simple: I typed “Implements IDisposable” and hit Enter. The IDE was “nice” enough to plugin the rest for me:

[vb language=".net"]

‘ To detect redundant calls
Private disposedValue As Boolean = False

‘ IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
Array.Clear(mDocumentContent, 0, mDocumentContent.Length)
End If
End If
Me.disposedValue = True
End Sub
[/vb]

It’s bad enough that the IDE writes code for me without prompting, but maybe the FxCop team should talk to the IDE team to avoid such embarrassing nuisances (I had dozens of similar warnings to weed through) in the future.

According to the Code Analysis Team, this is the new default for FxCop 1.36.

Here’s how to avoid it:

Using an FxCop project:

  1. Open your FxCop project in FxCop
  2. Choose Project -> Options -> Spelling & Analysis
  3. Check Suppress analysis results against generated code
  4. Click OK

OR, if you prefer the command-line:

  1. Pass the /ignoregeneratedcode switch, for example:

FxCopCmd.exe /file:MyAssembly.dll /out:AnalysisResults.xml /ignoregeneratedcode

Blog Traffic Exchange Related Posts Blog Traffic Exchange Related Websites
  • Home Improvement Comes Where to Begin Individuals need to try and do home improvement projects constantly to increase the value of their home. Several folks, but, do not understand that project to tackle initial once they have multiple projects to be done. Selecting which project to try and do initial can be set......
  • Windows Mobile, iPhone, Android - Marketplace Comparison Detailed comparison between Windows Mobile Marketplace, Apple's iPhone AppStore and Android Market from developer point of view. By: Predrag Tomasevic (Click for bigger image) Introduction The article you are about to read is my compilation of thoughts on three currently most popular and talked about mobile platforms, sparked by whole......
  • Development and remote installation of Java service for the Android Devices Written by: Igor Darkov, Software Developer of Device Team, Apriorit Inc. In this article I’ve described: How to develop simple Java service for the Android Devices; How to communicate with a service from the other processes and a remote PC; How to install and start the service remotely from the......
  • NetBeans IDE 6.7 Beta The NetBeans IDE is an award-winning integrated development environment available for Windows, Mac, Linux, and Solaris. The NetBeans project consists of an open-source IDE and an application platform that enable developers to rapidly create web, enterprise, desktop, and mobile applications using the Java platform, as well as PHP, JavaScript and......
  • Establishing Remodel Cost: Home Remodeling Critical First Step Nothing ruins a fantastic remodel more quickly than exceeding the project budget.  Why is this phenomenon so common in residential remodeling?  Simple:  Many homeowners struggle to establish a detailed budget at the appropriate time in the course of the project. Why is establishing remodel cost one of your most important......