Composite Control Properties
There are a couple of characteristics of composite control properties that need to be discussed. In the FormField rendered control you used a property coding technique that incorporated the using the ViewState variable to persist the internal value of the properties. In composite controls you have a couple of choices. You can choose to handle the properties the same way. This is fine for properties that define new characteristics of your control, but not really recommended for those that map directly to properties of child controls. The reason is that the child controls are already set up to handle state on their own. If you map their properties to properties in their container (the composite control) which also use ViewState to persist themselves, you run the risk of overbloating the ViewState. Remember that everything stored in ViewState gets rendered on the page in a hidden textbox called __ViewState
. The larger this gets, the more information has to travel through the pipe between the server and the browser.
ViewState is one of the more powerful features of ASP.NET and one that automatically takes care of a lot of stuff that you would otherwise have to handle manually, but like every other tool in your arsenal, you need to think ahead and use it wisely. Let's take a look at how you should code the CaptionWidth property of the EmailContact control, which as I've already said, will map to the CaptionWidth properties of some of the child controls.
Public Property CaptionWidth() As Unit
Set(ByVal Value As Unit)
ctlFromName.CaptionWidth = Value
'handle other child controls here too
public Unit CaptionWidth
this.ctlFromName.CaptionWidth = value;
//handle other child controls here too
The commented area in the preceding code would contain the code that sets the other FormField controls' CaptionWidth
properties, as well as that of the lblHeading
child control. This technique allows the child controls to maintain their state without the composite control repeating the task. Instead, the composite control simply maps its property to that of the child controls. Notice that the get
accessor returns the value of one control, while the set
accessor sets that of several (though only one is shown above). The one coded in the get
accessor can be any one of the child FormField controls. Since you're setting all of them, they will all be the same so you can return any one you want. Many properties will map to only one child control, as would be the case for the ButtonWidth
property. This property (whose code will not be shown) would map to the Width
property of the btnSend
child control in the same way shown above. The call to EnsureChildControls
is necessary to make sure that the child controls have been initialized before you try to access them. If they have not, then the CreateChildControls
method would be automatically called.
For properties that do not map directly to child controls, you would still use the ViewState technique you learned earlier. The ShowSubject
property, which I haven't talked about yet, does not map to any child control; it instead handles a specific behavior to the EmailContact control. This property is coded exactly as the ones you learned about earlier in the design of the FormField control with one additionThe set
accessor needs to set the ChildControlsCreated
property, which is inherited into your composite control, to false.
ViewState["ShowSubject"] = value;
this.ChildControlsCreated = false;
Setting this flag ensures an automatic call to the CreateChildControls
method so child controls are reset. Don't worry, that call does not occur upon the setting of this flag, so the flag can be set by the setting of many properties, and only calls to the method will take place upon the next page rendering. You can, in fact, use this style of property handling for all your properties but I would advise you to set the EnableViewState
property of the child controls to False
since you would no longer rely on their state maintenance ability. There would also be exceptions to turning state off in some child controls, as in the case of contained DropdownList
controls that rely on their own state to persist the contents of their list.
By providing plenty of appearance-oriented properties, that is properties that can hide or reposition child controls, you give your composite control maximum flexibility. The downloadable code extensively demonstrates this. Another thing handled in the CreateChildControls
is the application of styles. One again this is handled simpler in composite controls than in rendered controls.
Style properties are defined exactly the same as in the FormField control with the addition of the flag setting described earlier.
this.ChildControlsCreated = false;
The difference with styling in composite controls is how they are applied to the child controls defined within. If you look back at the earlier code defining the CreateChildControls
method you'll notice two methods used, one on the ctlSubject
control and a different one on the btnSend
control. Here's a C# recap.
When you designed the FormField control, which is the type of the ctlSubject
child control, you gave it several styling properties. The first thing you have to do with your EmailContact control in regards to styling is to define its styling properties as well, which as you can probably guess will somehow be mapped to the child controls. First of all, for simplicity, you would define the style properties exactly as you did in the FormField control, but once again with the addition of the ChildControlsCreated
setting. The way you would then "map" the style properties is with the CopyFrom
method of the Style object. That's all there is to it for those controls. The ApplyStyle
method used in the case of the btnSend
child control, applies the style property to the main style of the child control as opposed to a style property. The main style constitutes the styling properties inherited from the WebControl class. Remember these properties will apply styling to the control's container where added style properties add styling to elements within the control. This is the case in both the FormField and EmailContact controls. Remember, the btnSend
control is of type ConfirmationButton, which you'll recall inherits from the Button class. You did not add any custom styling to this control, and the Button class does not expose any style properties.
All the properties the Style object exposes are exposed by the WebControl class, which is the base of the Button class. As I said, ApplyStyle corresponds to these properties. The FormField control has these properties as well and is certainly compatible with ApplyStyle. Though you have not done so in your EmailContact, you can certainly add a styling property corresponding to the surrounding container of each contained FormField control. This property can then be applied to the child controls. However, you are mapping styling properties to the custom styling properties you gave the FormField control and that is done with the CopyFrom method.
The styling that the final version of the EmailContact control provides allows the control to be integrated into any Web site. Figure 2 and Figure 3 show pictures of the same control in two different sites.
There's one child control left for which you need to provide some special handling; this is the btnSend control. The intent of your control is to be able to send e-mails for you when a user clicks this button so you need to handle an event here.