Give the following control hierarchy on a ASP.NET page:
- Page
- HeaderControl (User Control)
- TitleControl (Server Control)
- TabsControl (User Control)
- other controls
- HeaderControl (User Control)
I'm trying to raise an event (or some notification) in the TitleControl that bubbles to the Page
level. Then, I'd like to (optionally) register an event handler at the Page codebehind that will take the EventArgs
and modify the TabsControl in the example above. The important thing to note is that this design will allow me to drop these controls into any Page and make the entire system work seamlessly if the event handler is wired up. The solution should not involve a call to FindControl()
since that becomes a strong association. If 开发者_JAVA技巧no handler is defined in the containing Page, the event is still raised by TitleControl but is not handled.
My basic goal is to use event-based programming so that I can decouple the user controls from each other. The event from TitleControl is only raised in some instances, and this seemed to be (in my head) the preferred approach. However, I can't seem to find a way to cleanly achieve this.
Here are my (poor) attempts:
Using HttpContext.Current.Items
Add the EventArgs to the Items collection on TitleControl and pick it up on the TabsControl. This works but it's fundamentally hard to decipher since the connection between the two controls is not obvious.
Using Reflection
Instead of passing events, look for a function on the container Page directly within TitleControl as in:
Page.GetType().GetMethod("TabControlHandler").Invoke(Page, EventArgs);
This will work, but the method name will have to be a constant that allPage
instances will have to defined verbatim.
I'm sure that I'm over-thinking this and there must be a prettier solution using delegation, but I can't seem to think of it. Any thoughts?
To make each control reusable and decoupled from other controls, I've always taken this approach: Each container will know about the controls that it contains one level deep, but not about the container containing it. To communicate up, you are correct in using events. This provides your layer of abstraction and makes all of your controls reusable.
That being said, let's take a look at your example. Your TitleControl
does not contain anything, so all it will do is fire events.
Your HeaderControl
references your TitleControl
and handles it's events. If it doesn't completely handle your TitleControl
's events, then have it declare and fire it's own event, and pass along the original sender and event args.
At your page level, your page will handle your HeaderControl
's events. Since your page is also the container for your TabsControl
, call a public method in your TabsControl
inside the event handler for your HeaderControl
's event and pass in the bubbled up EventArg information.
Basically, use events to bubble things up, and use public methods or properties to push things down.
Are you trying to do something along these lines?
You could have the Page implement an interface that has the events on them. Then have the tab control see if the page implents the desired interface. If it does then hook up to the events.
Missed the part about the title control. The title control would also have to make itself known to the Page via an interface method.
You could then hook up the events at some point (perhaps the load event). This would of course only work if the controls where added to the page prior to the load event.
The HeaderControl
can expose an event that gets consumed by the TabsControl
. I've answered a similar question before (with a sample project attached).
精彩评论