As part of the current site working on I have been developing a page framework that allows for user controls to have information loaded into them by a parent container control such that each user control within the parent control doesn’t have to retrieve the information which is an obvious performance problem.
The key to providing this functionality is during the OnLoad event of the parent control (the parent control itself is a UserControl). During the OnLoad I was recursively walking the page control tree to find any controls that implemented a certain interface which meant I could set a property on it.
All seemed to be working fine and it appeared that the property was getting set on all of the child controls until one of the other guys noticed that for some reason in his particular control that the property was not being loaded. Upon this realisation I set down a long and interesting path to try to figure out what made this control different to the others.
I spent quite a bit of time investigating and noticed that this control was trying to access the property during a formviews OnDataBound event handler however this didn’t make any sense because according to the page life-cycle there should really be no way that the OnDataBound event would be firing before the OnLoad event, or so I thought.
I spent quite a bit of time looking at various models of the page life-cycle trying to figure out how the hell this could be happening and didn’t really come up with any good reasons. In my last act of desperation I decided to look at the stack trace working back from when the NullReferenceException was thrown and I noticed that it seemed to stem back to my recursive control walking…AHAH!
The code I was using to walk the control tree looked something like this. What I noticed is that when the control that is stepped into is some form of templated control it would appear that the control is made to databind. In retrospect this makes sense, this is because in a templated controls the controls inside the template don’t exist at compile time they only exist once the container control has its databound.
So ultimately what was happening is that during the OnLoad of the parent control the recursive control walking was reaching a gridview, formview or similar and then causing that control to databind. In the databound the control was trying to use the property that normally would have been set during the OnLoad but this had not occurred yet.
The fix was simple! It was just a matter of ensuring that if a control is a DataBoundControl to not try to iterate through its controls. Of course this has a knock on effect that you cannot put a usercontrol in a databound control and expect to be able to use this “framework” to access it and have properties and such set. This isn’t really a problem for me however as in our project I have not seen one example with user controls inside databound controls (I’m talking about complex controls not just simple extended textbox and similar type of controls).
As a side note during looking for the code snippet for this article I noticed that I could have used ControlCollection.OfType however I’m not sure if this has the same problems with stepping into databound controls.
Hopefully someone gets some use out of this post and it makes some sense. I’m still working on my dependent validator solution and its taken a bit of a back seat with all of the hectic things going on at work right now.
Stay tuned for more….