After all the settings and behavior and layout details you've learned to pack into forms in this chapter, you may decide that you'd like to keep some of your hard work in a Form-derived base class for easy reuse by further derivations , and you can certainly do that. If you follow the convention that forms initialize their own properties and the properties of their child controls in a function called InitializeComponent, the Designer provides direct support for your visual inheritance : the reuse of a form base class via inheritance. Table 2.1. Parent Menu Merge Settings
Table 2.2. Child Menu Merge Settings
The goal of visual inheritance is to allow a base class to capture common UI elements, which are then shared and augmented by deriving classes. For example, imagine a BaseForm class that derives from Form and provides a menu bar, a status bar, and an icon, as shown hosted in the Designer in Figure 2.37. Figure 2.37. Base Class Used in Visual Inheritance
BaseForm can now serve as a base class for all forms that contain at least this functionality, [14] such as the EditorForm shown in Figure 2.38.
Figure 2.38. EditorForm Derived from BaseForm
The EditorForm class was created by deriving from BaseForm, overriding the Text property, adding the TextBox control to the form, and overriding the Text property of the status bar from the base class. I could have done this work by hand, but instead I created the EditorForm. I right-clicked on the project in Solution Explorer and chose Add Add Inherited Form. Then I set the form's name and chose BaseForm from the list of forms in the project displayed in the Inheritance Picker dialog, as shown in Figure 2.39. Figure 2.39. The Inheritance Picker Dialog
The initial EditorForm looked just like BaseForm except for the little arrow over the status bar (as shown in the lower-right corner of Figure 2.38). This arrow indicates a control inherited from the base. After inheriting the new form class from the existing form class, I used the Toolbox to add the new controls and used the Property Browser to change the form's Text property. However, to change the Text property of the status bar, I first had to change the access modifier. By default the Designer adds all fields as private, which means that they're accessible only from that class, the BaseForm class in our example. If you want to use the Designer to set a property on one of the controls in the base class from the deriving class, by default you can't until you change the access modifier in the field declaration in the base class: private StatusBar statusBar; You change the private keyword to protected to allow access by deriving classes: protected StatusBar statusBar; If you're really into Cooperesque [15] visual design, you can change this keyword by selecting the status bar on BaseForm using the Designer and changing the Modifiers field.
The purpose of this exercise in reuse is that when a new feature is needed across the set of forms that derive from BaseForm or when a bug is found, you can make the changes to the base form, and deriving forms automatically benefit. For example, BaseForm could add an Edit menu, and that would propagate to the EditorForm on the next compile. As nifty as visual inheritance is, it's not without its limitations. For example, although you can completely replace the main menu of a base form in a deriving form, you can't add or subtract menu items or replace menu item event handlers from the base. However, as a template mechanism to avoid duplicating controls and code, visual inheritance is definitely worth your consideration. |