[.net] Strange problem with adding buttons dynamically to webforms

Started by
15 comments, last by Zul 19 years, 6 months ago
I have this function (as well as another that is almost just like it). This function draws a table with some info, then I add a button. It worked while I actually had a table on the webpage, but when I try to add the table dynamically, it quits working:

Public Sub DrawSingleSystemWithButton(ByVal Position As Integer, ByVal Systems1 As MainSystems, ByVal NestedSystems1 As NestedSystems, ByVal ButtonText As String)
	Dim SystemTable As Web.UI.WebControls.Table = New Web.UI.WebControls.Table
	Dim ButtonRow As System.Web.UI.WebControls.TableRow = New System.Web.UI.WebControls.TableRow
	Dim ButtonCell As System.Web.UI.WebControls.TableCell = New System.Web.UI.WebControls.TableCell
	Dim MyButton As System.Web.UI.WebControls.Button = New System.Web.UI.WebControls.Button

	DrawHeaderRow(SystemTable)
	DrawSystem(Position, Systems1, NestedSystems1, SystemTable)

	MyButton.Text = ButtonText
	MyButton.Width = Unit.Percentage(100)

	ButtonCell.ColumnSpan = 2
	ButtonCell.Controls.Add(MyButton)

	ButtonRow.Cells.Add(ButtonCell)
	SystemTable.Rows.Add(ButtonRow)

	AddHandler MyButton.Command, AddressOf OnSelect

	Me.Page.Controls.Add(SystemTable)
End Sub

It used to be this (I just put a blank table on my asp.net page and passed it in, rather than declaring a table in the function and then doing Page.Controls.Add()). It worked fine like this:

Public Sub DrawSingleSystemWithButton(ByVal Position As Integer, ByVal Systems1 As MainSystems, ByVal NestedSystems1 As NestedSystems, ByVal ButtonText As String, ByRef SystemTable As System.Web.UI.WebControls.Table)
	Dim ButtonRow As System.Web.UI.WebControls.TableRow = New System.Web.UI.WebControls.TableRow
	Dim ButtonCell As System.Web.UI.WebControls.TableCell = New System.Web.UI.WebControls.TableCell
	Dim MyButton As System.Web.UI.WebControls.Button = New System.Web.UI.WebControls.Button

	DrawHeaderRow(SystemTable)
	DrawSystem(Position, Systems1, NestedSystems1, SystemTable)

	MyButton.Text = ButtonText
	MyButton.Width = Unit.Percentage(100)

	ButtonCell.ColumnSpan = 2
	ButtonCell.Controls.Add(MyButton)

	ButtonRow.Cells.Add(ButtonCell)
	SystemTable.Rows.Add(ButtonRow)

	AddHandler MyButton.Command, AddressOf OnSelect
End Sub

So I changed very little. Yet after the changes, it no longer works, and I get this error message:
Quote:Control '_ctl4' of type 'Button' must be placed inside a form tag with runat=server. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Web.HttpException: Control '_ctl4' of type 'Button' must be placed inside a form tag with runat=server. Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [HttpException (0x80004005): Control '_ctl4' of type 'Button' must be placed inside a form tag with runat=server.] System.Web.UI.Page.VerifyRenderingInServerForm(Control control) System.Web.UI.WebControls.Button.AddAttributesToRender(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.RenderBeginTag(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) System.Web.UI.Control.RenderControl(HtmlTextWriter writer) System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) System.Web.UI.Control.Render(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) System.Web.UI.WebControls.TableCell.RenderContents(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) System.Web.UI.Control.RenderControl(HtmlTextWriter writer) System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) System.Web.UI.Control.Render(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) System.Web.UI.Control.RenderControl(HtmlTextWriter writer) System.Web.UI.WebControls.Table.RenderContents(HtmlTextWriter writer) System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) System.Web.UI.Control.RenderControl(HtmlTextWriter writer) System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) System.Web.UI.Control.Render(HtmlTextWriter writer) System.Web.UI.Control.RenderControl(HtmlTextWriter writer) System.Web.UI.Page.ProcessRequestMain() -------------------------------------------------------------------------------- Version Information: Microsoft .NET Framework Version:1.1.4322.2032; ASP.NET Version:1.1.4322.2032
Does anybody know what the hell might be going on here?
Advertisement
I also note that by commenting out any of the following lines the program works (or course I don't get a button, and in the last case I get no table). If I comment out any other line it still throws the exception.

ButtonCell.Controls.Add(MyButton)
SystemTable.Rows.Add(ButtonRow)
Me.Page.Controls.Add(SystemTable)
Do you know how to use the command window?

If you have a try catch block around the code causing the error, you can step through one line at a time to the place where you catch the error. Then if you have a

catch ex as exception
throw new exception("bad things happened") <------------

Step to that line (after the exception happens). Bring up the command window and type ?ex.message, and you'll get the exact error message, which might shed a little more light on the subject.
oh hai
Ohhhhhhh, wait a minute. How are you calling that function? Since you're trying to add a server side button, the message is telling you that it must be placed within the form tag of your asp page, which it isn't doing. If you use a script tag within your html page where you want that button to appear, you shouldn't get the same error.

Like this:

<form>
.....stuff
<%DrawSingleSystemWithButton%>

.....more stuff

</form>

I don't know if that will work with the rest of your page functionality though...
oh hai
Any web control which causes a postback (Button, LinkButton etc) must be placed inside a <form> tag with runat="server" this caused the buttons to post back correctly.

So essentially what Zul said above but runat server must be set as well.
I'm unable to do that with the way I have it working. Can't I do like GenericButton.attributes("RUNAT", "SERVER") or something like that?

I have n number of buttons. The number of buttons is decided by how many items I have in my dataset. This is a selection screen where you hit the button below an entry. I don't know the number of buttons beforehand, so I can't really add them to my page except how I have it. There is no way around this?
Its not an issue of your button having runat="server". Its the fact that your button needs to be inside a form with it.

You can encase you entire aspx page in this form. The default page from Visual Studio looks like this.
<body MS_POSITIONING="FlowLayout">
<form id="Form1" method="post" runat="server">
... your content here ....
</form>
</body>
This is really odd, because I've done this sort of thing before. The code is the same, except I don't pass the table in. When I had the table as an argument and put the table on my page, it worked just fine (it didn't have a problem with my dynamic buttons at all). When I make the table dynamically and add it dynamically, the button doesn't work (what does this table have to do with the button?). Like I said, if I put a table on my aspx page and pass it into the function, this works just fine. I have several pieces of code where I have a button that isn't part of the page. I don't see how this is any different from my other code (you can see it in my first post) other than I don't pass the table in anymore. Weird.

Quote:Original post by xg0blin
This is really odd, because I've done this sort of thing before. The code is the same, except I don't pass the table in. When I had the table as an argument and put the table on my page, it worked just fine (it didn't have a problem with my dynamic buttons at all). When I make the table dynamically and add it dynamically, the button doesn't work (what does this table have to do with the button?). Like I said, if I put a table on my aspx page and pass it into the function, this works just fine. I have several pieces of code where I have a button that isn't part of the page. I don't see how this is any different from my other code (you can see it in my first post) other than I don't pass the table in anymore. Weird.


This is exactly the problem. When the table is placed on the page, it is already encased within the <form> tag. If you're trying to add it dynamically, Response.Write won't add it within the <form> tag unless your script call is placed within the <form> tag.

Now, what you can do if you don't want to have a table automatically on the page (if it doesn't have any data) or whatever, why not use panels on the page? I use this all the time. Set up the panels on the page the way you want each part to be, and then use your server side code to add tables whereever you need them.

Since I'm pretty curious on the matter, and also would like to use the functionality, I'm going to do a little research on adding page items dynamically to be server side.
oh hai
Quote:Original post by Zul
Quote:Original post by xg0blin
This is really odd, because I've done this sort of thing before. The code is the same, except I don't pass the table in. When I had the table as an argument and put the table on my page, it worked just fine (it didn't have a problem with my dynamic buttons at all). When I make the table dynamically and add it dynamically, the button doesn't work (what does this table have to do with the button?). Like I said, if I put a table on my aspx page and pass it into the function, this works just fine. I have several pieces of code where I have a button that isn't part of the page. I don't see how this is any different from my other code (you can see it in my first post) other than I don't pass the table in anymore. Weird.


This is exactly the problem. When the table is placed on the page, it is already encased within the <form> tag. If you're trying to add it dynamically, Response.Write won't add it within the <form> tag unless your script call is placed within the <form> tag.

Now, what you can do if you don't want to have a table automatically on the page (if it doesn't have any data) or whatever, why not use panels on the page? I use this all the time. Set up the panels on the page the way you want each part to be, and then use your server side code to add tables whereever you need them.

Since I'm pretty curious on the matter, and also would like to use the functionality, I'm going to do a little research on adding page items dynamically to be server side.


Ok, I get it now. Duh. Thanks Zul, I wish I had more rating points to give you.

It sucks they made it that way, because I don't want all the hastle of having to add this crap to my page, when it is simpler to just call a function. Oh well I guess.

This topic is closed to new replies.

Advertisement