Just after writing the post above, I came across a blog post very much in the same discussion by Dave Reed [Infinity88].
I'm going to call "store the property value to the viewstate and set the child control property in CreateChildControls" method the "ViewState Method". The "expose child control properties directly and use EnsureChildControls in Init or in each property accessor" method the "Expose Method".
Dave seems to be thinking along the same lines as I am - that the ViewState Method of exposing child control properties is inefficient, causing duplicates - but Dave brings up another good point: the ViewState Method fails once CreateChildControls is called at run-time. Read Dave's blog for details.
Comments on Dave's blog by Stefaan Rillaert and Simone Busoli also hit upon the same design-time issue as I had with the Expose Method, it doesn't work at design-time. Both methods are trying to overcome the shortcomings of the other; the ViewState Method works better at design-time, the Expose Method works better at run-time. So what's the "holy-grail" solution?
Busoli mentions in Reed's blog that using the Expose Method and overriding RecreateChildControls as
protected override void RecreateChildControls()
{
EnsureChildControls();
}
solved the Expose Method's state-loss-at-design-time issue in his case, but that method isn't going to work for a control like the new .NET 2.0 LoginControl which renders different templates based on a property value. In that case, simply calling EnsureChildControls wouldn't clear the control tree and recreate the alternate template as desired. My implementation of RecreateChildControls I listed in my last post will aslo fail in this case, since the view state cannot be restored if the owning controls are missing from the control tree.
It feels like the CompositeControlDesigner's method of calling RecreateChildControls whenever any property is changed in design-mode is a hammer too large for the nail. I can't think of a catch-all solution, but perhaps there isn't one. Some design-time property changes are going to require the control tree to be rebuilt, some will only require a redraw. The answer may be to create a PropertyAttribute that indicates whether a property change at design time should generate a rebuild or a redraw. The default action would be a redraw, but special properties like the one that changes the template for the LoginControl would be marked as "cause design-time rebuild".
Are there any resources that offer a good examination of design-time attribute classes? We've probably all seen Description and Category, but I've just recently run into RefreshProperties and NotifyParentPropertyAttribute which are still a bit of a mystery. There may already be a property attribute that accomplishes what I'm suggesting, but I'm not sure where to look.
Ryan Rahlf