I have this issue where I'm trying to generate HTML to display on the page that is coming from the database in form of a template that has different curly brackets that get replaced with dynamic content at run time. For example curly bracket {Content} gets replaced with a few checkboxlists, radiobuttonlists, textboxes and a submit button. The way I'm doing this is by creating controls dynamically and rendering them as string and then outputting that string to the browser. But what this does is, it doesn't recognise the events assigned to the controls when they are generated. I may be taking a wrong approach to the issue, but I don't really see how else this can be achieved. I have put up some sample code below to show what I'm trying to achieve. Please advise how to resolve this.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim PageContent As StringBuilder = New StringBuilder()
PageContent.Append("A lot of content from database laid out using HTML templates stored in database including the below mentioned button code.")
'# To illustrate how pagecontent is built using lots of such controls rendered to string
Dim SubmitButton As Button = New Button()
SubmitButton.ID = "MySubmitButton"
SubmitButton.Text = "Submit"
SubmitButton.CssClass = "SubmitButton"
'Page.Controls.Add(SubmitButton) '# This line I thought would resolve the issue, but it doesn't as the .net form is not built at the time of page load
AddHandler SubmitButton.Click, AddressOf ClickHandler
PageContent.Append(RenderControlToString(SubmitButton))
Dim Output As Literal = New Literal()
Output.Text = PageContent.ToString()
Page.Controls.Add(Output)
End If
End Sub
''' <summary>
''' Button Click Hander
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub ClickHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
'# Control never gets here!!!!!
Response.Write("<br/>Button Clicked!")
Response.End()
End Sub
''' <summary>
''' Render control to string
''' </summary>
''' <param name="control"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function RenderControlToString(control As Control) As String
Dim sb = New StringBuilder()
Using sw = New StringWriter(sb)
Using textWriter = New HtmlTextWriter(sw)
control.RenderControl(textWriter)
End Using
End Using
Return sb.ToString()
End Function
Thanks for advising!
Use the PreInit event, as explained here, http://msdn.microsoft.com/en-us/library/ms178472.aspx, this is where you will want to add dynamic controls. In fact you should just have to do the Page.Controls.Add() , since this is happening early enough in the page life cycle, ASP should handle the rendering for you.
controls must be initiated in Page_Init to persist them in viewstate and if control does not exist in viewstate, aspx won't understand whos event was registered. Initialize ur button on page_init
Dynamically loading controls in .Net is a little confusing. I see four problems with what you're doing.
You're trying to dynamically add the controls only on the initial HTTP GET (not on postbacks). You need to add the controls every time. You're not binding data here, you're adding controls to the Page control tree. Those controls need to be added every time the page runs.
You're rendering controls to string. Don't do that, just add them to the page control tree and they'll render on their own during the page Render.
Use Page.LoadControl() when creating controls. This will create the control and force it's events (page event lifecycle) to catch up with the rest of the page.
You're adding controls a little late in the page event lifecycle. Try adding your controls in Page_Init.
Here's a sample that pulls it all together. It dynamically creates a button and then adds it to a placeholder control.