OFGemini
asked on
When to add dynamically loaded controls?
In an ASP.NET page, I have an UpdatePanel with dynamically a loaded child control (using the Page.LoadControl method). I know I have to create the control and add it to the page after every postback (even asynchronous), but there seems to be one of two problem regarding when, in the lifecycle of the page I do this.
A) If I create the control during the page's OnInit (or CreateChildControls or OnLoad) phase, events in the parent page have not been processed yet, so I don't know exactly which control to load.
B) If I create the control during the page's OnPreRender(or OnLoadComplete) phase, things look fine, but the dynamic control will not respond to any postback events.
When it the preferred time in a page's lifecycle to create dynamically loaded controls?
A) If I create the control during the page's OnInit (or CreateChildControls or OnLoad) phase, events in the parent page have not been processed yet, so I don't know exactly which control to load.
B) If I create the control during the page's OnPreRender(or OnLoadComplete) phase, things look fine, but the dynamic control will not respond to any postback events.
When it the preferred time in a page's lifecycle to create dynamically loaded controls?
'Here is a summary of the important methods
'This function only gets called if the viewer is created during initialization
Protected Overrides Function OnBubbleEvent(ByVal source As Object, ByVal e As EventArgs) As Boolean
Dim handled As Boolean = False
If TypeOf e Is CommandEventArgs Then
Dim ce As CommandEventArgs = DirectCast(e, CommandEventArgs)
Select Case ce.CommandName
Case "Show"
ViewerCode = ce.CommandArgument
handled = True
End Select
End If
Return handled
End Function
'SomeSub is any procedure in the page's lifecycle
Protected Overrides Sub SomeSub()
If _viewer Is Nothing Then
LoadViewer()
End If
MyBase.SomeSub()
End Sub
Private Sub LoadViewer()
Dim ViewerPath As String = DecodeViewerPath(ViewerCode)
_viewer =Page.LoadControl(ViewerPath)
ViewerUpdatePanel.ContentTemplateContainer.Controls.Clear()
ViewerUpdatePanel.ContentTemplateContainer.Controls.Add(_viewer)
ViewerUpdatePanel.Update()
End Sub
'This function only gets called in the right order if the viewer is created after initialization
Private Sub TreeView_SelectedNodeChanged(ByVal sender As Object, ByVal e As EventArgs) Handles TreeView.SelectedNodeChanged
ViewerCode = TreeView.SelectedNode.Value
End Sub
Dynamically created controls can be tricky for exactly the reasons you say.
It's ok to add a dynamic control in say, a button click event handler, but if the control you add raises a postback itself then in the next postback it must be added to the page before postback events are raised, which happens after page_load and before prerender.
As an example, say I have a button on my page which when clicked adds a dynamic control, which itself has a button in it, the process would need to be:
(Page button click)
Page_Init -> (do nothing)
Button_Click -> Add the dynamic control.
(Dynamic control button click)
Page_Init -> Add the dynamic control.
The tricky part here is how to handle the logic of adding the control in different page events depending on the circumstances. I'd suggest adding a value to viewstate which specifies whether you need to create the control, you can then check this each postback to detarmine whether to recreate the control. So the above would become:
(Page button click)
Page_Init -> Check Viewstate("ControlToCreate ") -> nothing required
Button_Click -> Add the dynamic control. Set Viewstate("ControlToCreate ")
(Dynamic control button click)
Page_Init -> Check Viewstate("ControlToCreate ") -> Create required control.
Hope this helps.
It's ok to add a dynamic control in say, a button click event handler, but if the control you add raises a postback itself then in the next postback it must be added to the page before postback events are raised, which happens after page_load and before prerender.
As an example, say I have a button on my page which when clicked adds a dynamic control, which itself has a button in it, the process would need to be:
(Page button click)
Page_Init -> (do nothing)
Button_Click -> Add the dynamic control.
(Dynamic control button click)
Page_Init -> Add the dynamic control.
The tricky part here is how to handle the logic of adding the control in different page events depending on the circumstances. I'd suggest adding a value to viewstate which specifies whether you need to create the control, you can then check this each postback to detarmine whether to recreate the control. So the above would become:
(Page button click)
Page_Init -> Check Viewstate("ControlToCreate
Button_Click -> Add the dynamic control. Set Viewstate("ControlToCreate
(Dynamic control button click)
Page_Init -> Check Viewstate("ControlToCreate
Hope this helps.
ASKER
This seems to be very similar to the solution I'd posted (only you suggest using Init rather than Load), correct? I should point out that in my snippet, ViewerCode just is a wrapper for a viewstate variable
On_Init (On_Load) -> read viewstate, create controls
On_Some_PB_Event -> set viewstate, create controls
This still seems a little bit clumsy as the 'create controls' step could be (or in my case, is likely to be) fairly expensive. Unless someone can suggest an alternative solution, this will have to do.
On_Init (On_Load) -> read viewstate, create controls
On_Some_PB_Event -> set viewstate, create controls
This still seems a little bit clumsy as the 'create controls' step could be (or in my case, is likely to be) fairly expensive. Unless someone can suggest an alternative solution, this will have to do.
Private Property ViewerCode() As String
Get
Return Return If(CStr(ViewState("ViewerCode")), String.Empty)
End Get
Set(ByVal value As String)
ViewState("ViewerCode") = value
End Set
End Property
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
In short, no, it's not enough. I already rely on events bubbling up through the dynamic control without knowing precisely where the event originated.
I light of this, I suppose there is no good work around.
I light of this, I suppose there is no good work around.
ASKER
I'm still looking for a better, cleaner solution.
Open in new window