ee if you can tell what's wrong with the following sequence: ND, MN, WI, SD, NE, KS, MO, IL, IN. Unless you have a PhD in North American geography, you may have trouble even realizing that there is a potential problem much less finding it. If you take a look at Figure 1
, however, the problem is obvious. There's a gaping hole in this group of Midwestern states.
|Figure 1. Selecting States: The StateSelector control makes problems in state selections obvious.|
A few years ago, I worked on a fuel tax application for the state of Minnesota. Each year, a trucking company reports the states where it purchased fuel and the states where it actually drove. Then after a long series of Byzantine calculations, the company sends Minnesota a check for $4.17.
In this application, I built a dialog similar to the one shown in Figure 1 to let the users select and view states graphically. While the selection shown in Figure 1 is conceivable, it's pretty unlikely. Unless the company's owner once got a bad haircut or had some other traumatic experience in Iowa, it's pretty unlikely that the company would operate in all the surrounding states, but skip Iowa. Visuals can help immensely in some circumstances. For example, while it's difficult to determine a missing state from a string of state abbreviations such as "ND, MN, WI, SD, NE, KS, MO, IL, IN," the omission becomes obvious in the graphical representation.
This article isn't really about the StateSelector control shown in Figure 1 (although the control is contained in the downloadable sample project that accompanies this article). Instead, this article is about making controls easier to use. It explores some tools that you can provide to make life easier for developers who use your controls. These tools let developers view and modify control properties at design-time by using smart tags, command verbs, property pages, custom editors, and special property representations in the Properties window.
A Few Warnings
Before you hear about this control's special design-time features, you should be warned: building these features into your controls is rather tricky. Not because the code is particularly complicated—it isn't—it's somewhat involved but surprisingly short. These techniques are tricky for three main reasons.
First, these techniques are not very well documented. The online help describes each of the tools you need separately, but you need to find an article such as this one to put all the pieces together.
Second, tools that help developers at design time run in a strange in-between mode, neither in the control's run time nor in the control's design time. While you are manipulating the control in the IDE at design time, UI editors and classes that display the control's properties in the Properties window execute in their own special runtime. Because they don't run in the control's runtime, you don't have complete control over their code. For example, you cannot set breakpoints in the code, and it's sometimes hard to get the code to even respond directly to the user with message boxes, so debugging can be quite difficult. When something goes wrong, the IDE may display no message and no editor at all, giving only a relatively unhelpful error message such as "Object reference not set to an instance of an object," or even a downright confusing message similar to my personal favorite "Could not convert value StatesMapControls.StatesMap to the type StatesMapControls.StatesMap."
Finally, sometimes the editors seem to get "stuck" or somehow cached in the IDE. Even after you make a change to one of the control's editors, the IDE still tries to use an older version and gets thoroughly confused. (This causes the "Could not convert" message in the previous paragraph.) The easiest way to fix this is to remove all instances of the control from the forms, close the IDE, reopen the IDE, rebuild the project, and then add a new instance of the control to the form. After a while, you get pretty good at unclogging the IDE in this way—I can do it in about 10 seconds. If you make a change to the code but don't see any difference in the result, give it a try before you start throwing things.
Because of all these difficulties, you may want to skip the whole issue. If you plan to use the control yourself only once or twice, or if you only plan for one or two other developers to use the control, then you might want to ignore these design-time tools and do something more productive like watching Futurama reruns.
However, if you plan to use the control a lot, give the control to a lot of other developers, or sell the control to other programmers, then it may be worth your while to provide some or all of these special design time tools. In that case, grab your favorite caffeinated beverage and read on.