views:

585

answers:

3

Here's the problem....I have three components...A Page that contains a User Control and a Server-side control which is in the user control. The user control has a handful of events that the page listens to which change what the server-side control does.

The server control essentially creates a TV-Guide looking list filled with many many smaller ASP.NET controls that need to have events. All of these controls are created dynamically (server side obviously). Populating this server side control requires operations that are intensive in nature and should therefore be only done once per postback. Event1 and Event2 fire and basically will change things about the serverside controls rendering (sorting, filtering etc) so when they fire I need to call PopulateControls for sure.

Here's the problem: I cannot find the best place to put the call to PopulateControls. If i put it in the PageLoad, it fires and draws the list before any events. Then my events have to call PopulateControls themselves to respond to the event. If i put the call in PreRender, the server-side control's events do not fire because from what i read, they need to be created before or during PageLoad.

So where do i put this call so that I only have to call it once and so that it can respond to the proper events?

Here's some psuedo code

public class MyPage : System.Web.UI.Page
{
    protected UserControl MyUserControl;

    // Wire up event handlers
    MyUserControl.Event1 += OnEvent1;
    MyUserControl.Event2 += OnEvent2;

    public Page_Load()
    {
    }

    public PreRender()
    {
        PopulateControls();
    }

    private PopulateControls()
    {
        // Do intensive operation to populate controls
    }

    protected OnEvent1()
    {
    }

    protected OnEvent2()
    {
    }
}
A: 

Child controls ought to be created in CreateChildControls, which is called in the "Init" phase of control life-cycle.

jachymko
Agreed but that doesn't solve my problem. If i create them there, I'll have to RECREATE them again when my event fires later because the event changes what needs to be drawn.
cjserio
A: 

The best place to call events that you want called before anything else occurs on your page, or any child controls, is in the PageInit stage.

Here is a decent article that discusses the page life cycle with user controls: http://www.codeasp.net/articles/asp.net/20/aspnet-page-lifecycle

AaronS
I'm not calling any events...The events are in response to something the user did...For instance, OnClicks etc. They are hit after Page_Load just by the nature of the way .NET works.
cjserio
If I understand your question correctly, you want an event in your usercontrol to fire before anything else does. This would then trigger events in other places, like in your page. In this case, then you need to put your control binding logic in the PageInit of your control, not the page itself.
AaronS
I'm confused...I don't think the order of events can be adjusted. See http://msdn.microsoft.com/en-us/library/ms178472.aspx. Control Events always occur after the Page_Load has already completed.
cjserio
+1  A: 

I might be missing something here, but I will take a crack at this anyway. You have to create the control hierarchy the same as it was on the inital rendering for you ids to match and allow your events to fire properly. It sounds like you need to do some reordering after an event fires so you will need to create the controls twice.

Edit: You need to be able to recreate your controls and the control hierarchy on post back. You should send enough information to the client so that you can recreate the controls correctly on Postback. This can be done by saving information in ViewState if necessary.

You should only recompute the control inforation when it is required. In your case because of some post back event.

The basic flow should be like this. In you Load event, if you don't have the ViewState needed to create your controls, call your populate method, otherwise create them from ViewState. When a post back occurs, the Load event will create them, but they are being reconstructed from viewstate so this should be cheap. When the post back event fires, call you populate method to recreate the controls in the new order or with the new information, depending on what event happened.

Whenever I am building a control I like to think about how the control will behave if a post back occurs from some other control on the page. Your control should continue to look the same unless affected by that post back and it should be able to be recreated without doing any data access, but from information it has collected on previous calls.

I edited my answer and hopefully this is a littler clearer now.

Daniel