Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles
This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

By David Callahan (October 2008)
We take a look at planned support for parallel programming for both managed and native code in the next version of Visual Studio.

By Stephen Toub and Hazim Shafi (October 2008)
Here we describe some of the more common challenges to concurrent programming and present advice for coping with them in your software.

By Joe Duffy (October 2008)
Here is an ASP.NET AJAX data-driven Web application that takes the best features from server- and client-side programming to deliver an efficient, user-friendly experience.

By Bertrand Le Roy (October 2008)
More ...
Articles by this Author
IntroducingOn10.net (http://on10.net), the Channel 9 answer for the technology enthusiast who isn’t necessarily a programmer.

By Duncan Mackenzie (December 2006)
The My Namespace is best described as a speed-dial for the .NET Framework. It provides an intuitive navigation hierarchy that exposes existing .NET functionality through easily understood root objects. Here Duncan Mackenzie explains it all.

By Duncan Mackenzie (Visual Studio 2005 Guided Tour 2006)
My four-year-old son has decided that he wants to be like his dad when he grows up. He is planning to work in my office, and write computer programs just like I do. But there is one problem—he thinks I write games.

By Duncan Mackenzie (October 2005)
Many applications need to store user-specific settings to be persisted between sessions. But how do you go about saving and restoring these settings in your Microsoft® . NET Framework-based application? It's not all that easy to find the correct answer.

By Duncan Mackenzie (April 2005)
I have to admit it; most of my Windows® Forms controls are an attempt to copy something that already exists. In my October 2004 column I showed you how to create a progress bar that mimicked the one shown during the Windows XP setup routine, and this month I'm at it again.

By Duncan Mackenzie (January 2005)
As a parent of a young child, I take a lot of pictures—many more than anyone would ever be interested in seeing. Well, anyone except my mother. This is her first grandchild and the one or two pictures I send to her each week only brush the surface of her grandmotherly needs.

By Duncan Mackenzie (November 2004)
In many situations, accurately estimating the length of a certain process (copying a large file, loading data from a server, retrieving files from the Internet) would be both difficult and inefficient.

By Duncan Mackenzie (October 2004)


By Duncan Mackenzie (July 2004)
More ...
Popular Articles
Efficient parallel applications aren’t born by merely running an old app on a parallel processor machine. Tuning needs to be done if you’re to gain maximum benefit.

By Rahul V. Patil and Boby George (June 2008)
One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

By Dan Griffin (May 2008)
We introduce you to the benefits of building composite applications with the Composite Application Guidance for WPF from Microsoft patterns & practices.

By Glenn Block (September 2008)
Here we present a rundown of the various language paradigms of CLR-based languages via short language introductions and code samples.

By Joel Pobar (May 2008)
More ...
Read the Blog
Well designed code keeps things that have to change together as close together in the code as possible and allows unrelated things in the code to change independently, while minimizing duplication in the code. In the October 2008 issue of MSDN Magazine, Jeremy Miller shows you some design ...
Read more!
The process for ink capture and analysis on the Tablet PC is straightforward in managed code. To the uninitiated developer, however, creating unmanaged Tablet PC applications can be rather daunting. In the October 2008 issue of MSDN Magazine, Gus Class a quick introduction to the Tablet PC ...
Read more!
Multicore systems are becoming increasingly prevalent, but the majority of software today will not automatically take advantage of this additional processing ability. And multithreaded programming, for anything but the most trivial of systems, is incredibly difficult and error prone today. In the October 2008 issue of MSDN ...
Read more!
Concurrent programming is notoriously difficult, even for experts. You have all of the correctness and security challenges of sequential programs plus all of the difficulties of parallelism and concurrent access to shared resources. In the October 2008 issue of MSDN Magazine, David Callahan describes ...
Read more!
A major advantage of AJAX and Silverlight applications is that they can transparently and continuously interact with a back-end service. The problem is that they run over HTTP, which wasn't designed with security in mind. In the September 2008 issue of MSDN Magazine, Dino Esposito shows you ...
Read more!
Unhandled exception processing shouldn't be a mystery. It's actually quite useful since it gives a crashing application an opportunity to perform last-minute diagnostic logging about what went wrong. In the September 2008 issue of MSDN Magazine, Gaurav Khanna discusses how ...
Read more!
More ...
Advanced Basics
Creating A Breadcrumb Control
Duncan Mackenzie

Code download available at: AdvancedBasics0507.exe (152 KB)
Browse the Code Online
Hansel and Gretel had the right idea when "they followed the pebbles that glistened there like newly minted coins, showing them the way." The deeper you get into the forest or into your data, the more likely you are going to need help to find your way back out again. On the MSDN® Web site, and many others, the way out is represented by a navigational element in the header of the page that shows your current position in the site. Clicking on any of the links to the left of your current position takes you to that location, providing a quick path to find more related information or to get back to the starting point of the site.
This type of navigation is often referred to as "breadcrumbs" and is most appropriate when your information is organized in a hierarchical structure, with many levels, and works well in the same situations in which a TreeView would be used. Data often maps well to a tree-like structure, so this style of data representation is often found in all sorts of apps, both Windows® and Web-based.
My own applications are no exception; I'm currently working on a new app in which the main method of navigation will be through a tree that displays the structure of a complete Web site, and another tree that represents a single page. Because I am so familiar with the breadcrumb control on MSDN, I decided that I would employ that functionality in my application.

Building a Breadcrumb Control
When the user selects a single page deep within the site, I would like to show them their current position and, at the same time, make it easy to move back up the hierarchy to any point. They will have a TreeView, of course, but I don't think that a tree is as clear and easy as a horizontal list of past locations. So, I decided that I would create a breadcrumb control in Windows Forms.
When you are looking at the code sample, you'll notice that my control is called an "Eyebrow" instead of a breadcrumb. Eyebrow is the name used in MSDN code, and it just stuck in my mind. You're probably wondering how this control relates to an eyebrow. So am I. I know my eyebrows don't have any information about my current position, and they certainly don't help me get around, but that's what they're called in the code, so that's how it'll be.
Back to the control. The control works by being associated with a TreeView. You can configure that association programmatically or through the property grid in Visual Studio® at design time. The control's rendering is then based on information in the associated TreeView, namely the currently selected node.
By hooking the tree's selection changed event (AfterSelect), the control is notified whenever it needs to be redrawn. The associated TreeView is accessed directly to find the currently selected node, to navigate up through all of the parent nodes, and to change the selected node when the user clicks on one of the hyperlinked items. By obtaining all of its navigational information from the TreeView, the breadcrumb control doesn't have to know anything about your particular application. As long as you set up and populate your TreeView and handle the tree's events, this control should work within your application.

Drawing and Clicking
The real core of the control falls into two areas: rendering the control and tracking which areas of the control should be clickable. The first task, the rendering, isn't doing anything really special if you are used to GDI+ coding. I build up a collection of tree nodes in the current node's path, then walk through them from top to bottom, and write out the appropriate text, as shown in Figure 1.
As I go through this drawing loop, I'm building up a collection of ClickArea objects, which associate a specific tree node with an area of the control. This process, and the collection it creates, is the key to properly handling mouse over and click events.
When the user brings the mouse over the control, a search through the collection of ClickArea objects is executed (shown in Figure 2), and each one in order is checked to see if the current mouse position is contained within the associated Region. If the mouse is over a clickable region, the pointer is changed to the Hand cursor, indicating to the user that something should happen if they click on this point (see Figure 3). The code that changes the cursor is shown in Figure 4.
Figure 3 Hovering Over a Link 
In the OnClick procedure of the control, the same search is performed, but in this case if a node is found, the current selection of the tree is updated to point to the clicked item:
Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
    Dim pos As Point = Me.PointToClient(Me.MousePosition())
    Dim node As TreeNode
    node = FindNode(pos)

    If Not node Is Nothing Then
        Me.m_tree.SelectedNode = node
    End If
End Sub
Updating the SelectedNode of the tree will in turn cause the tree's AfterSelect event to fire, causing the Eyebrow control to be redrawn.

All the Bells and Whistles
Never content to leave something in its simplest state, I added some additional properties to the control: AutoSize, Wrap, and ShowImages. The first two are closely related, because AutoSize only works if Wrap is set to true. Setting both these properties to true causes the control to wrap text to a new line if necessary (Wrap) and to increase its height as required to display all the text (AutoSize). If a single node's text is wider than the control, then it is trimmed instead of wrapped because my code only supports wrapping between complete items. This is shown in Figure 5.
ShowImages may be useful if you use images in your tree and if those images are meaningful to your users. If you set it to true, then when drawing out the individual item, the image is pulled from the TreeView's associated ImageList and drawn next to its text on the Eyebrow control, as shown here:
'grabbing the image from a TreeNode in OnPaint
Dim img As Image
If m_ShowImages AndAlso Not Me.Tree.ImageList Is Nothing Then
    img = Me.Tree.ImageList.Images(n.ImageIndex)
End If

'drawing the image next to each item
If Not img Is Nothing Then
    g.DrawImageUnscaled(img, startingPos)
End If
Including support for images complicates the sizing and wrapping code, but the visual effect will be worth it in most applications. The end result is shown in Figure 6.
Figure 6 AutoSizing, Wrapping, and Images 

Conclusion
As usual, I haven't built everything into this control that you will probably want; it is a sample after all. I can think of three key additions that you may eventually want: the ability to control the image position (upper left, middle right, and so on), an option to use a separator image between items, and more complex display options for when space is limited. The control in its present state is a good place to start, though, and should open up some interesting navigation options for your tree-based apps.

Send your questions and comments for Duncan to  basics@microsoft.com.


Duncan Mackenzie is a developer for MSDN and the author of the Coding 4 Fun column on MSDN online. He can be reached through his personal site at www.duncanmackenzie.net.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker