in

ASP.NET Weblogs

Andy Smith's Blog

Page.RegisterStartupScript('Andy', 'MetaBuilders_WebControls_GainKnowledge();');

subclassing and working with your events

I see code like this alot, and there is a bit of a problem with it under certain circumstances.

protected override OnFoo(EventArgs e) {
 base.OnFoo(e);
 //Do My Thing
 if ( bar ) {
  DoSomeReallyCoolStuff();
  System.NeatThings.NeatnessLevel = NeatnessLevel.High;
  /*
  Line And Lines of really interesting code here
  */
 }
}

Code like that is the general advice for people who want to derive from a class, and want to do stuff before/during/after a certain event. It is a much better idea than handling your own events. However this can cause a real problem for people who want to derive from your superdooper class. You see... you've combined the raising of an event with code that needs to happen during an event. With code like this, there is no way for me to derive from your class, and change this code that happens during OnFoo, without also stopping the Foo event from being raised.

A much better way to do this is something like this:

protected override OnFoo(EventArgs e) {
 base.OnFoo(e);
 DoMyThing();
}
protected virtual DoMyThing() {
 if ( bar ) {
  DoSomeReallyCoolStuff();
  System.NeatThings.NeatnessLevel = NeatnessLevel.High;
  /*
  Line And Lines of really interesting code here
  */
 }
}

Now a derived class can rip out this implementation of DoMyThing much more independantly of the raising of the Foo event.

If you need a real world example to see what I'm talking about... I had thought about adding support for item groups in the DropDownList and ListBox controls. In html, this is done by adding OptGroup tags around Options. I was planning on looking at a custom "group" attribute in the ListItem to see if I should create a group. But then I got to thinking about databinding, and that it's not really usefull unless I can support that easily too. So I thought that I could add a DataGroupField string property, which would set the group attribute on the new ListItems as they were being created. I was ok with the idea of reimplemening the databinding code, but then this problem hit me. The ListControl class has the code which creates the ListItems directly in the OnDataBinding method. This means that I have to override that method, and not call the base OnDataBinding, in order to implement my group data binding. But if I do that, then my control never raises its DataBinding event. And for those of you wondering why I can't just call the base OnDataBinding, and then run thru the datasource again to bind the group property to the list items... I can't do that because not all datasources can be run thru twice, such as a DataReader, which, for better or worse, is commonly used in web apps for data binding.

Comments

 

Mike said:

Andy,

I just wrote some similar code this morning (putting all of my code into the OnWhatever method).

I was refactoring it this afternoon so I could extract a base class from the object (inherited from TreeView - I was implementing Drag/Drop) and ended up wondering how to do it. This is great advice, and exactly what the doctor ordered. Thanks for the post.
September 30, 2003 6:59 PM
 

George Gonsalves said:

Have you actually an implementation of a dropdownlist box with optgroup support...
August 5, 2004 4:48 PM
 

Joel said:

*bump*

Does MS support optgroup like it should yet?

July 5, 2007 9:01 PM

Leave a Comment

(required)  
(optional)
(required)  
Add