Home arrow ASP.NET arrow Page 2 - Custom Controls and Design-Time Support: Part 1/2

Custom Controls and Design-Time Support: Part 1/2

Creating custom controls is a key technique in .NET development. This article by Matthew is the first of a two part series where he looks at how to create a custom Windows Form control that behaves properly in Visual Studio .NET.

Author Info:
By: Wrox Team
Rating: 5 stars5 stars5 stars5 stars5 stars / 24
December 03, 2002
  1. · Custom Controls and Design-Time Support: Part 1/2
  2. · Inherited Controls in C#
  3. · The DirectoryTree Control (contd.)
  4. · Attributes
  5. · Conclusion

print this article

Custom Controls and Design-Time Support: Part 1/2 - Inherited Controls in C#
(Page 2 of 5 )

.NET supports three basic types of custom controls for Windows Forms applications:
  • User controls inherit from the System.Windows.Forms.UserControl class, and follow a model of composition. User controls represent the simplest type of control, and generally combine more than one existing .NET control in a logical unit (like a group of text boxes for entering address information).
  • Inherited controls derive from another .NET control that provides the basic functionality. The .NET class library is filled with examples of inherited controls. For example, LinkLabel derives from Label and CheckedListBox derives from ListBox.
  • Owner-drawn controls derive from the base System.Windows.Forms.Control class, and provide their own drawing logic. With an owner-drawn control, the programmer needs to manage every aspect of the control's behavior, including details like mouse clicks.
In this article, we'll consider an example of an inherited control. Inherited controls are an ideal way to take functionality from the .NET base classes and extend it. Inherited controls can closely resemble their parent class, or they can be dramatically different, with a unique properties, methods, and events.

Control Projects
Custom controls are nothing more than custom classes that derive from a .NET base control class. That means you can add them to any .cs code file, and even create them alongside your application code, in an ordinary Windows Forms project. However, the easiest way to develop custom controls is in a separate dedicated project. This approach makes it possible to reuse the control as a compiled assembly DLL. It also gives you an opportunity to add and test the required design-time support. If you add an inherited control to an ordinary project, you won't be able to add the control to the Toolbox or test its design-time support.

The easiest way to begin coding a custom control is to create a Class Library Project (which is recommended for most custom control projects) or a Windows Control Project (which is generally used for user controls). Both of these selections work equally well-the only difference is in the default references that are set, and the namespaces that are initially imported into your project. The important detail is that you are creating a library project, which creates a DLL assembly, not a stand-alone executable. You can create a class library project that contains several files and multiple controls, or you can create a separate project and assembly for each custom control you make.

When you begin your control project, you will probably find that you need to add a few assembly references and import some namespaces:
  • Typically, you'll need to add references to the System.Windows.Form.dll, System.Drawing.dll, and System.Design.dll assemblies.
  • Useful namespaces include System.Windows.Forms, System.ComponentModel, and System.Drawing. Importing namespaces isn't required-it's just a handy convenience that helps trim down long lines of code.
To build your project at any time, right-click on it in the Solution Explorer and choose Build. The DLL file will be placed in the bin\debug or bin\release subdirectory of your project directory, and can be shared with any other project that needs to use the control.

The DirectoryTree Control
The DirectoryTree control inherits from the standard TreeView, and adds the features needed to display a hierarchical view of directories. .NET does not include any type of native directory control, so this TreeView is genuinely useful.

The DirectoryTree provides the following functionality:
  • Adds a Drive property that allows the programmer to specify what drive will be shown.
  • Refreshes its display automatically, but "just in time" as branches are expanded. This ensures optimum performance, particularly on large hard drives.
  • Raises a higher-level DirectorySelected event that provides information about the directory a user has clicked on. This allows you to use the DirectoryTree on its own, or create a basic Windows Explorer type of application by updating a ListView with file items every time the DirectorySelected event occurs.
The basic structure for the TreeView control is shown below. A DirectoryTree namespace includes both the control and the custom event arguments object used for the DirectorySelected event:

using System;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;

namespace DirectoryTree
public class DirectoryTree : TreeView
// Code omitted.

public class DirectorySelectedEventArgs : EventArgs
// Code omitted.

The basic public interface of the DirectoryTree class includes the Drive property (which allows a single Char to represent the drive letter), and the DirectorySelected event:

public delegate void DirectorySelectedEventHandler(object sender,
DirectorySelectedEventArgs e);
public event DirectorySelectedEventHandler DirectorySelected;

char _drive;

public char Drive
return _drive;
_drive = value;

The DirectoryTree is populated in the RefreshDisplay method. Note that the DirectoryTree fills itself by reading sub-directories as the appropriate branches are expanded. That means that the control operates very quickly, even if the drive has tens of thousands of subdirectories. Only the expanded directory levels are actually shown. The collapsed branches all have a dummy node inserted:

// This is public so a Refresh can be triggered manually.
public void RefreshDisplay()
// Erase the existing tree.

// Set the first node.
TreeNode rootNode = new TreeNode(_drive + ":\\");

// Fill the first level and expand it.

void Fill(TreeNode dirNode)
DirectoryInfo dir = new DirectoryInfo(dirNode.FullPath);

// An exception could be thrown in this code if you don't
// have sufficient security exceptions for a file or directory.
// You can catch and then ignore this exception.

foreach (DirectoryInfo dirItem in dir.GetDirectories())
// Add node for the directory.
TreeNode newNode = new TreeNode(dirItem.Name);

blog comments powered by Disqus

- How Caching Means More Ca-ching, Part 2
- How Caching Means More Ca-ching, Part 1
- Reading a Delimited File Using ASP.Net and V...
- What is .Net and Where is ASP.NET?
- An Object Driven Interface with .Net
- Create Your Own Guestbook In ASP.NET
- HTTP File Download Without User Interaction ...
- Dynamically Using Methods in ASP.NET
- Changing the Page Size Interactively in a Da...
- XML Serialization in ASP.NET
- Using Objects in ASP.NET: Part 1/2
- IE Web Controls in VB.NET
- Class Frameworks in VB .NET
- Cryptographic Objects in C#: Part 1
- Sample Chapter: Pure ASP.Net

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 

Developer Shed Affiliates


© 2003-2018 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials