Wednesday, October 24, 2007

ApplyStyleSheetSkin On System.Web.UI.Control?

I've been a big fan of the theme support which was added in ASP.NET 2.0, especially when I found the StyleSheetTheme property which lets me control at what time the skin values are applied.

Lately I've been building some reusable ASP.NET AJAX controls which are built by extending the ExtenderControl class which is a part of ASP.NET AJAX 1.0. I have been making reusable controls which serve a general purpose for the application I am working on. I like to make the control entirely configurable so I provide many properties which are settable by the consumer of that control.

I then wrap that control in a composite control with the control it extends and add context to this control. For example I may make a really cool auto complete type control and then make a composite control that understands my customer object. The composite control would include a textbox and the autocomplete ajax extender control. The control would also include information on how the list of customers should be filtered or anything else which is specific to the context of a customer.

Now, I've built many composite controls using these AJAX controls, but how do I define defaults for all of the controls? For example I want 250 millisecond delay for the AJAX control before making a web service request to filter what the user entered, how do I set this by default for all items on the site?

My first attempt was to make wrapper properties on the composite control that just exposed the child properties of the underlying autocomplete control. This works well, then I create one item in the skin of my active theme per composite control and away I go. This works, but it is areal pain, and it seems like there should be a better way.

I later stumbled upon the ApplyStyleSheetSkin method of the System.Web.UI.Control class. This looks perfect. I can call this method on my AJAX control which inherits from the ExtenderControl since ExtenderControl inherits from System.Web.UI.Control. This will be perfect. I'll just have to add one item to my skin file and then all composite controls can automatically share these defaults! What could be simpler? I can't believe I didn't know about this earlier.

So I give it a shot and see an error message saying the method only works on System.Web.UI.WebControls.WebControl! But then why put the method on System.Web.UI.Control? And why make no reference to it on the MSDN documentation? Meanwhile, I'm back to square one, making wrapper properties and duplicate entries in my skin file. Why all of the confusion Microsoft? This one makes no sense!

Yes I know I can just use IExtenderControl and basically build my own ExtenderControl which inherits from System.Web.UI.WebControl but that is a lot of logic I would prefer Microsoft worried about and I feel it shouldn't be necessary!

-John Chapman


flip44 said...

Another thing you could do along the lines of the SKIN would allow your control to read fron the Appsettings of the ConfigurationManager for some of these common properties. This may allow you more flexibility w/o having to repush if your settings need to change.

flip44 said...

Another thing you could do would be to read from the AppSettings of the ConfigurationManager. Very similar to the skin if you want a GLOBAL setting, also may allow you a little more flexible change in a prod environment if your values change frequently. You wouldn't have to make a PUSH (this assumes that the Skin File isn't updatable which in your case it might be).

John Chapman said...

Flip, you raise valid points, but I guess I was just viewing these controls a little differently. These controls are intended to be usable across all applications. How often do you need to add web.config settings when you add a textbox to an application? Typically you configure the textbox (like MaxLength) with a property, and if you want a default you use a stylesheetskin. The .config file would certainly work though, it just didn't seem like the clean approach. That being said, this method should just work. I can't figure out why it exists on the System.Web.UI.Control yet can't be used on an item which inherits from it but not WebControl!

Blogger Syntax Highliter