Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#
Article

Drill-down Combo Control

Rate me:
Please Sign up or sign in to vote.
4.57/5 (22 votes)
22 Dec 20056 min read 148.3K   1.3K   94   10
A flexible drill-down combo control supporting hierarchical, cascading selections.

Image 1

Introduction

How many times in a UI is there a requirement for a control containing several combo boxes, where the list of potential selections in any given combo is dependent on previous selections in other combos? As an example, consider a website that deals in second-hand cars:

Image 2

The user enters a Manufacturer, a Configuration (sedan, station wagon, hatch), followed perhaps by Gear-box type (manual, automatic) and Year of model. Finally, they get to the category in which they actually want to make a selection - the Model. This technique is so ubiquitous because it is so powerful - imagine a user having to select a model of car from all models ever made by any manufacturer!

The goal of this control is to not only provide a managed way of cascading user selections, but also to provide a schema for storing the configuration data behind the control. The control should be:

  • fully configurable in terms of categories, values, and dependencies;
  • easily configured at run-time by passing in the data from a store (i.e., the categories, values, and dependencies should live in an independent data store such as a database or an XML file, so that categories can be easily added or removed, or their order changed); and
  • independent of the type and location of the data store (data abstraction).

Background

Before diving in, here's a bit of a glossary for the rest of the article. If you have any suggestions for changing these terms to make them clearer for future readers, I'm all ears!

Category

A category represents a scale for values. The scale has no direction (or order). On the control, each category is represented by a combo box.

Value

A value is one of a set for each category. A value has no intrinsic meaning apart from the fact that it is distinct from other values in the set - i.e., it has no type such as "real number" that implies things such as order and arithmetic operations. Any meaning attached to a value is dependent on its interpretation, which is aided by the description of the category to which it belongs (so values could be interpreted as numbers, if this is a property of the category to which they belong). Values are what the user selects in each combo box.

Set of categories

The categories themselves form a set - the set of categories! The programmer should be able to manage this set without coding, including addition and removal of members, as well as the order of members (the categories fall on an ordinal scale determining the order in which they are presented to the user).

Enumeration

An enumeration is an ordered set of values, one for each category in the category set.

Partial enumeration

A partial enumeration is an ordered set of values, one per category, from the first category to an arbitrary category that is not the last (e.g., values for Manufacturer, Configuration and Gear-box, but not for Year and Model).

Total enumeration

The total enumeration of a tree is a list of all possible paths from the root to the leaves. In our case, the total enumeration represents every valid ordered combination of values.

Leading category(ies)

For any given category, those preceding it in category order are its leading categories.

Trailing category(ies)

For any given category, those succeeding it in category order are its trailing categories.

Limitations

Before going on, I should mention one major limitation of this control. In some cases, there is a requirement that the next trailing category be determined by a user's selection. For instance, if the user selects "bird" from an "animals" category, then the next trailing category might be "beak type". However, the "beak type" category would be inappropriate if the user had selected, for example, "fish". This type of tree is not supported by the drill-down control. For one thing, it would mean that the control could not provide an overview of what input is required from the user, since combo boxes would have to appear one at a time based on user selections (this frustrates me on some websites, especially when the server is slow!). Perhaps a tree-like control (ala Explorer, Regedit) would be more appropriate where this is a requirement.

Using the code

To use the code, just drop a DrillDown control on a form. Use the Initialise method to set up the control. This method will label the combos and populate them with a default enumeration:

C#
/* connect to a data store */
System.Data.OleDb.OleDbConnection con = 
    new System.Data.OleDb.OleDbConnection(connectionString);
con.Open();

/* set up a DrillDownDataSet */
DrillDownDataSet d = new DrillDownDataSet();

System.Data.OleDb.OleDbDataAdapter adap;

/* fill the DrillDownDataSet */
adap = new System.Data.OleDb.OleDbDataAdapter(
                    "SELECT * FROM Categories", con);
adap.Fill(d.DdCategoriesTable);

adap = new System.Data.OleDb.OleDbDataAdapter(
                    "SELECT * FROM Outputs", con);
adap.Fill(d.DdOutputsTable);

adap = new System.Data.OleDb.OleDbDataAdapter(
                    "SELECT * FROM Enumerations", con);
adap.Fill(d.DdEnumerationsTable);

MyDrillDown.Initialise(d);

Initialise takes a DrillDownDataSet. The schema of this strongly typed DataSet is shown below:

Image 3

The table DdCategories describes the set of categories, including their order. For example:

DdCategoryIdentifierDdCategoryNameDdCategoryOrdinal
1Colour of Item:0
2Type of Item:1
3Name of Item:2

The table DdEnumerations is a normalized table of enumerations constituting the total enumeration. Every enumeration is expected to be linked to the full complement of categories. An example is shown below:

DdEnumerationIdentifierDdCategoryIdentifierDdValue
11Red
12Vegetable
13Rhubarb
21Red
22Vegetable
23Tomato
31Red
.........

The table DdOutputs maps each enumeration to an output value, an integer. It is up to the programmer to decide whether the mapping is one-to-one or one-to-many. The output value is a representation of what the user has ultimately selected using the drill-down. An example is shown below:

DdEnumerationIdentifierDdOutput
10
21
32
43
54
65
76
87
......

Based on the data in the examples above, the control might look as follows:

Image 4

Behind the scenes

Behind the scenes, the control makes use of the DataTable and DataView objects to manage cascading. When the Initialise method is called, the control sets up a denormalised (or "flat") table, with one category per column and one enumeration per row. A user selection simply triggers a cascading filter on the trailing categories.

Features

One of the features of this control is that, in order to save the state of the drill down, all the programmer needs to do is store the enumeration identifier or the output value associated with the user's selection. This is done via the EnumerationId and Output properties. Setting either property restores the control to the appropriate state. In the case of a non-unique output, the control is set back to the first valid enumeration matching the said output. The enumeration identifier is always unique.

A second feature of the control is that it tries to remember user selections in the trailing categories. If a selection is still valid when a leading category changes values, then that selection will remain. That way, the user needs to re-enter as little data as possible in case of a correction up the hierarchy.

Points of interest

Discovered the strength of the DataRelation object in typed DataSets. This object makes it very easy to work with relational data in memory.

History

  • 21st December, 2005
    • Added IncludeBlankEnumeration property to the control to force default blank combos. Also modified the code to allow spaces in the category names.
  • 22nd August, 2004
    • Added properties to control the appearance of run-time generated category combos.
  • 10th August, 2004
    • Initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Engineer
Australia Australia
Ken is a mechanical engineer with an interest in programming in .NET.

Comments and Discussions

 
GeneralMy vote of 1 Pin
AshokReddyProjects12-Nov-10 20:47
AshokReddyProjects12-Nov-10 20:47 
GeneralMy vote of 4 Pin
AshokReddyProjects12-Nov-10 20:42
AshokReddyProjects12-Nov-10 20:42 
Questionhow do set the imagelist? Pin
skurge21-Dec-04 9:12
skurge21-Dec-04 9:12 
AnswerRe: how do set the imagelist? Pin
omcken18-Jan-05 13:40
omcken18-Jan-05 13:40 
Sorry for the late reply skurge, been on holiday. You've probably figured this out by now, but the image list is populated at design time in the IDE. If you are using VS, just look up "images, adding to ImageList component" in the help and you'll get examples for adding images at design time or programmatically. Hope this helps...

Ken Wahren
Mechanical Engineer
OMC International
Generalthanks Pin
skurge15-Dec-04 0:56
skurge15-Dec-04 0:56 
GeneralNice. Pin
derekdevdude19-Aug-04 20:28
derekdevdude19-Aug-04 20:28 
GeneralLike It Pin
jasonhawryluk18-Aug-04 21:49
jasonhawryluk18-Aug-04 21:49 
Generalgood article, Ken Pin
BillWoodruff18-Aug-04 14:15
professionalBillWoodruff18-Aug-04 14:15 
GeneralNot really a limitation Pin
SBJ17-Aug-04 9:57
SBJ17-Aug-04 9:57 
GeneralRe: Not really a limitation Pin
omcken17-Aug-04 14:01
omcken17-Aug-04 14:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.