Depending hard on being inserted into the control tree
Note: this entry has moved.
This morning while I was waiting for an ASP.NET talk at the MVP Summit I noticed that my weblog was a *bit* outdated… so I decided to blog about one of the 5783 things that I was saving for later.
Some controls tend to depend on being added to the control tree in order to work properly before they can be used. For example, it’s common to see code like this in a Control’s Render method:
base.Page.GetPostBackClientEvent(this, "");
this will cause an exception if you use the control in a way like this:
MyControl a = new MyControl ();
// MyControl is never inserted into the control tree
// because of this Page property will be null
// MyControl.RenderControl uses Page, bad things will happen
a.RenderControl (writer);
The solution to this is to program the control’s Render method in a more flexible way, that is, considering that the control may not be inserted into the control tree while someone may still want to get its rendering, i.e.:
if (base.Page != null)
base.Page.RegisterRequiresPostBack (this);
Of course if you’re dealing with a third-party or built-in ASP.NET control you just can’t modify the way the control was coded. So what?
Play nice as the CheckBoxList does
Insert the control to the control tree just so it gets its properties properly set (Page, ID, etc). This is actually what ASP.NET’s CheckBoxList control does in its public ctor: it instantiates a CheckBox and inserts it into its control tree. It is safe then to call CheckBox.RenderControl because its Page property will be already set, i.e.:
MyControl a = new MyControl ();
Controls.Add (a);
a.RenderControl (writer);
Or cheat do as the RadioButtonList does
UPDATE: I just checked and Control.Page property does has a set accesor, so I believe I may have been confused by the compiler inlining the call to the set accesor.
Instead of adding it to its control tree, RadioButtonList will set the Control.Page property by using code like this:
MyControl a = new MyControl ();
a.Page = this.Page
Relax a bit, as Whidbey does
Obviously if its makes sense for some of the functionality of your control to be used even if it’s not inserted into a control tree then by all means you should make that easy for the developers using your control; this means that every time you write code that uses the Page property you should check if it’s non-null.
Both CheckBox & RadioButton in v1.x don’t follow this advice. At some point they assume that Page will be always non-null and that’s why any of the previous two detailed solutions will be needed.
Luckily Whidbey changes this. The new CheckBox & RadioButton had been modified to relax a bit their dependencies on being inserted into the control tree. They now carefully check Page being a non-null reference before trying to use it.