RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Gain Design-Time Power with Control Editors, Part 2 of 2 : Page 3

Learn how to add custom editing dialogs, smart tags, and property pages to your controls.

Creating Property Pages
When you first create a StateSelector control, you are most likely to want to set its Map and LineStyle properties. You are much less likely to want to use the Properties window to set its Anchor, Dock, Location, Locked, Margin, MaximumSize, MinimumSize, Modifiers, Padding, RightToLeft, Size, and other properties that come with any control. A smart tag popup lets you put all the key properties at the developer's fingertips without all of the miscellaneous debris in the Properties window.

Smart tag real estate is limited, however; there's only so much you can squeeze onto a simple popup. When you need more property-setting functionality than the combination of the Property window and smart tags provides, consider using Property Pages.

Property pages provide an alternative to smart tags. They can be quite large—so you can put considerably more information on them than you can cram onto a smart tag popup. They can be so large, in fact, that they can host large, complex controls. Figure 4 shows the StateSelector control's property pages. The Map tab shown in the figure contains a StateSelector control that lets you determine the states that are selected on the map. (This feature provides another nice use of a StateSelector control to edit a StateSelector control!)

Figure 4. A Property Page in Action: Property pages work well when you need to use large, complex controls or group property items into tabbed pages to set properties.
Property pages can include any number of tabs, meaning you can have page after page of information when appropriate. Separate tab pages let you group related properties and information so it's easier for users to find the things they want to modify.

To provide a smart tag, you add the Designer attribute to the control's Class declaration. To provide property pages, you add the Editor attribute as shown in the following code fragment:

   <Editor(GetType(StateSelectorEditor), _
     GetType(ComponentEditor))> _
   Public Class StateSelector
   End Class
The editor for the StateSelector control is the StateSelectorEditor class. The StateSelectorEditor class shown in the following code is quite simple. It inherits from the WindowsFormsComponentEditor class and overrides two methods. The GetComponentEditorPages method returns an array of types describing the classes used in the property pages. The GetInitialComponentEditorPageIndex method returns the index of the first page the editor should display:

   Public Class StateSelectorEditor
      Inherits WindowsFormsComponentEditor
      ' Return an array of pages.
      Protected Overrides Function GetComponentEditorPages() _
      As System.Type()
         Return New Type() { _
            GetType(ppBasics), _
            GetType(ppMap) _
      End Function
      ' Initially display page number 0.
      Protected Overrides Function _
      GetInitialComponentEditorPageIndex() As Integer
         Return 0
      End Function
   End Class
The StateSelectorEditor class's GetComponentEditorPages function returns information about the two property page classes ppBasics and ppMap. The key pieces of these classes perform roughly the same functions so only ppMap is shown here. Listing 2 shows the most interesting portions of the ppMap class.

The ppMap class includes a ToolboxItem attribute with its value set to False so the property page doesn't appear in the Toolbox. The class inherits from the ComponentEditorPage class.

The next part of the class mimics the structure of a form, UserControl, or other visible container—including declarations for controls and components that appear on the page. If the code needs to handle an object's events, its declaration includes the WithEvents keyword.

The class's constructor creates the controls and components and initializes their properties much as a form does when it loads. In fact, you can take advantage of the similarity to make building the property page easier. First, build a temporary form that contains all the controls and components that you need on the property page. Arrange them nicely. Then open the Designer.vb file that defines that form. (In the Solution Explorer window, click the Show All Files button, expand the form, and open the Designer.vb file.) Then copy the code that declares and initializes the form's controls from the Designer.vb file to the property page class. Delete the temporary form when you're done.

The end of the class's constructor sets code for the property page itself. In particular, it sets the page's tab text and icon.

The property page class must override two methods so it can edit the control. First, it must override the LoadComponent method to copy properties from the control onto the property page. In this example, the LoadComponent method initializes the lblMapLoaded control to display either "(none)" or "(map)" depending on whether the control has a map loaded. If a map is loaded, it sets its StateSelector control's Map property to a clone of the editing control's Map value. This version of LoadComponent also copies the BorderColor, SelectedColor, DeselectedColor, Selected, and LineStyle properties from the control being edited to the property page's StateSelector control.

The second key method that a property page class must override is SaveComponent. This method should copy the modified values stored in the property page back to the control being edited. The ppMap property page lets the user change only two properties: Map and Selected. Its SaveComponent method needs to save only those values.

A property page may also include other code to handle the controls it contains. In this example, if the user clicks on the lblMapLoaded control, the Click event handler displays a file selection dialog to let a user pick a new map file. If the user picks a file and clicks OK, the event handler loads the new map and changes the label's text to (map). It also calls the property page's inherited SetDirty method to notify the property page editor that the values on this page have been changed, which causes the editor to enable the OK and Apply buttons shown in Figure 4. If the user clicks either of those buttons, the editor calls the page's SaveComponent method to save the changes.

Finally, if the user selects or deselects a state in the property page's StateSelector control, the sselMap_SelectedChanged event handler executes. This event handler simply calls the page's SetDirty method to indicate that the data has changed.

The rest of the property pages' operation is automatic. When the user right-clicks the control and selects Properties, the IDE displays the property pages, initially selecting the page indicated by the GetInitialComponentEditorPageIndex method.

Easier, Intuitive Custom Controls
This two-part article discussed how you can create powerful tools that make your custom controls much easier and more intuitive to use at design time. While convenient for users, bear in mind that these tools are fairly complex so implementing all of them for infrequently used controls may not be worth the effort; it may be easier to set the control's properties in code. However, if you plan to use the control repeatedly—or more importantly, give it to other developers or sell it to customers—you'll probably find it worthwhile to implement at least some of these tools. If you're trying to decide how long your control might be in use, remember the lesson of Y2K; code that was initially expected to last only a few years was still in use decades later. Providing functional type converters and editors may be more work now, but may save you time and effort down the road.

You can find more information about building design-time tools in my book Expert One-on-One Visual Basic 2005 Design and Development.

Rod Stephens is a consultant and author who has written more than a dozen books and two hundred magazine articles, mostly about Visual Basic. During his career he has worked on an eclectic assortment of applications for repair dispatch, fuel tax tracking, professional football training, wastewater treatment, geographic mapping, and ticket sales. His VB Helper web site receives more than 7 million hits per month and provides three newsletters and thousands of tips, tricks, and examples for Visual Basic programmers.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date