 |
| ASP.NET 2.0 Basics If you are new to ASP or ASP.NET programming with version 2.0, this is the forum to begin asking questions. Please also see the Visual Web Developer 2005 forum. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the ASP.NET 2.0 Basics section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

April 3rd, 2007, 08:59 AM
|
|
Authorized User
|
|
Join Date: Dec 2006
Posts: 35
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Dynamically Added Control ID changes
Hi,
I've got an ascx file called UserControl.ascx with the following. Note the id is 'txtEmail' :
Code:
<asp:TextBox Columns="30" TabIndex="2" ID="txtEmail" runat="server" CausesValidation="True" CssClass="input" MaxLength="255" />
I add the control to a placeholder in my aspx. vb :
Code:
Dim myUserControl As UserControl = LoadControl("UserControl.ascx")
' Add the control to the place holder
Me.placeholder.Controls.Add(myUserControl)
Me.placeholder.Visible = True
The control is in a form which gets submitted.
When I check the Form values 'txtEmail' has no value because the id of the control was somehow changed to 'ctl07_txtEmail'.
What has happened? Do I now have to write additional code to find the txtEmail field within the posted form fields?
Thanks for any help.
http://www.thewebsiteshop.co.uk
__________________
http://www.thewebsiteshop.co.uk
|
|

April 3rd, 2007, 10:02 AM
|
|
Authorized User
|
|
Join Date: Dec 2006
Posts: 35
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Ok,
I seem to have got around this although I guess it's a hack.
The reason this happens is best described here: http://odetocode.com/Articles/450.aspx (Find "Name Mangling") - even though I'm not using Master pages here as the article describes.
I added the following to my aspx page:
Code:
<asp:HiddenField ID="hdnClientID" runat="server" />
Then changed my aspx. vb like so
Code:
' Add the control to the place holder
Me.phUserCreate.Controls.Add(myUserControl)
' Store the client id so that we can reference the controls after posting
Me.hdnClientID.Value = myUserControl.ClientID
' Show the placeholder
Me.phUserCreate.Visible = True
Now when I post the Form I append the client id to the original control id, a la:
Code:
If IsPostBack Then
Dim sClientID As String
' Retrieve the client id so that we can access form values
sClientID = Request.Form("ClientID") & "$"
myUser.Email = Request.Form(sClientID & "txtEmail")
http://www.thewebsiteshop.co.uk
|
|

April 3rd, 2007, 11:35 AM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2003
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
|
|
Why aren't you accessing the value of the textbox thru the textbox control??
The user control should have a member named "txtEmail" so you can code directly against that:
txtEmail.Text
You should *almost* never never never need to manually access the forms collection.
That fellow calling it "name mangling" I think is a little harsh. And it has nothing to do with Master pages. This behavior has been with .NET from the beginning for a good reason. The explanation is simple.
The textbox is a child control of your user control. The user control is a child control of a page. If there are 2 instances of the user control on a single page, there are also 2 textboxes. If the textbox was render with it's ID intact, you would have 2 "txtEmail" form elements which you can't do. So .NET prepends the parent (or "nameing container") to the ID. But all of this doesn't matter if you are access stuff from the server side code. However, if you want to touch the controls from the client side, then you need to take this into account. The simplest answer is to use the control's ".ClientID" property, which will give you the fully qualified client-side ID of the control. That you can use in JS to locate the element.
But this doesn't change the fact that you should not need any of this for your code. It should look like this:
If IsPostBack Then
Dim sClientID As String
' Retrieve the client id so that we can access form values
myUser.Email = txtEmail.Text
If you are trying to do this from the PAGE, you should create a public property on the user control that encapsulates the code that looks at the textbox:
Public ReadOnly Property Email As String
Get
Return txtEmail.Text
End Get
End Property
- Peter
|
|

April 3rd, 2007, 02:28 PM
|
|
Authorized User
|
|
Join Date: Dec 2006
Posts: 35
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Peter,
Many Thanks for your reply.
I'm quite new to .NET but experienced with classic ASP. I definitely think I'm missing something here.
My understanding is that the textbox control simply generates the html input box that gets sent to the client. Yes, I can programmatically manipulate the control whilst on the server but once it has been sent to the client it is simply an html input tag in an html form.
I set my input tag up to have an id called 'txtEmail', yet when the html is generated .NET decides that I might not be capable of writing valid markup and so changes it for me ;)
The client doesn't send back a textbox control with a user input - it sends back the form element which (in classic ASP, at least I access through the Request.Form collection) and it is this element which I expect to be called 'txtEmail' that I am trying to get to.
I guess .NET probably does lots of clever stuff and keeps the textbox control and the input form element in sync using viewstate and this is probably where I have reached the limits of my understanding so far.
Anyway, if I try your suggestion I get the following error in the IDE:
Name 'txtEmail' is not declared
so I can't access it directly.
Kind Regards,
Paul
http://www.thewebsiteshop.co.uk
|
|

April 3rd, 2007, 02:36 PM
|
|
Friend of Wrox
|
|
Join Date: Jun 2003
Posts: 2,189
Thanks: 5
Thanked 59 Times in 57 Posts
|
|
hi there..
since you render the control at run time, the IDE doesn't know that it will exist when you run it...
so you have to do a findcontrol on your page, frame or placeholder, and that will return a handle to your textbox.
to findcontrol you pass the real id that you used, and .net will give you back the control that you want...
HTH
Gonzalo
================================================== =========
Read this if you want to know how to get a correct reply for your question:
http://www.catb.org/~esr/faqs/smart-questions.html
^^Took that from dparsons signature and he Took that from planoie's profile
================================================== =========
My programs achieved a new certification (can you say the same?):
WORKS ON MY MACHINE
http://www.codinghorror.com/blog/archives/000818.html
================================================== =========
|
|

April 3rd, 2007, 03:40 PM
|
|
Authorized User
|
|
Join Date: Dec 2006
Posts: 35
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi,
Gonzalo - thanks for the advice.
The HasControls() method on the placeholder returns false after posting the form.
First I tried this:
Dim txtEmail As TextBox = phUserCreate.FindControl("txtEmail")
myUser.Email = txtEmail.Text
and got this : Object reference not set to an instance of an object.
Then I tried invoking the HasControls method and got False.
Response.Write(phUserCreate.HasControls())
Response.End()
Kind Regards,
Paul
http://www.thewebsiteshop.co.uk
|
|

April 3rd, 2007, 03:52 PM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2003
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
|
|
First off, I forgot during the course of this discussion that you were adding the user control dynamically. So I haven't provided as good an answer as I could have. That's why you can't access that textbox by name.
Quote:
quote:
My understanding is that the textbox control simply generates the html input box that gets sent to the client. Yes, I can programmatically manipulate the control whilst on the server but once it has been sent to the client it is simply an html input tag in an html form.
|
Exactly.
Quote:
quote:
I set my input tag up to have an id called 'txtEmail', yet when the html is generated .NET decides that I might not be capable of writing valid markup and so changes it for me ;)
|
If you really feel that way. .NET renders ALL the controls, so don't feel bad. It's changing the ID sent to the client in order to maintain order among all the other controls, as I explained earlier.
Quote:
quote:
The client doesn't send back a textbox control with a user input - it sends back the form element which (in classic ASP, at least I access through the Request.Form collection) and it is this element which I expect to be called 'txtEmail' that I am trying to get to.
|
Yes, but this isn't classic ASP. If you are going to add user controls dynamically, you need to do so on both ends of a page interaction. If you add the control when the page initially loads, you should ALSO add the control in the say way when the page posts back. That way, you CAN access the controls child controls using pure server side code rather than relying on what you expect a form ID will be when it's posted. It doesn't take much to change the page's control tree and that will create a world of hurt for your app.
You'll need to maintain some information (possible in viewstate) that tells you what control(s) were added so you can re-add them to restore the control tree to the way it was when the page was first rendered. (I imagine this is what .NET does internally when you have complex data bound controls like lists or grids.)
- Peter
|
|

April 4th, 2007, 01:44 AM
|
|
Authorized User
|
|
Join Date: Dec 2006
Posts: 35
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi,
Thanks Peter. I tried your suggestion but still no luck.
Code:
If Page.IsPostBack Then
' Create an instance of the User Controls class
Dim myUserControl As UserControl = LoadControl("UserControl.ascx")
' Add the control to the place holder
Me.phUserCreate.Controls.Add(myUserControl)
Dim txtEmail As TextBox = phUserCreate.FindControl("txtEmail")
Response.Write(txtEmail.Text)
Response.End()
resulted in
Code:
Object reference not set to an instance of an object.
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.NullReferenceException: Object reference not set to an instance of an object.
Kind Regards,
Paul
http://www.thewebsiteshop.co.uk
|
|

April 4th, 2007, 04:13 AM
|
|
Authorized User
|
|
Join Date: Dec 2006
Posts: 35
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Ok guys,
I've made some progress.
First I moved the code that loads the control into the Page_Init event, as suggested in a number of other forum posts.
Then I used this neat little function I found at http://aspnet.4guysfromrolla.com/art...81402-1.2.aspx
Code:
lblText.Text += "[list]"
IterateThroughChildren(Me)
lblText.Text += "</ul>"
Private Sub IterateThroughChildren(ByVal parent As Control)
For Each c As Control In parent.Controls
lblText.Text = lblText.Text & "<li>" & c.ToString & " - " & c.ID & "</li>" & vbCrLf
If c.Controls.Count > 0 Then
lblText.Text = lblText.Text & "[list]" & vbCrLf
IterateThroughChildren(c)
lblText.Text = lblText.Text & "</ul>" & vbCrLf
End If
Next
End Sub
This displays all the controls within the page and I could see that txtEmail was indeed in there.
After some jiggery pokery, I managed to extract the value.
Code:
Dim txtEmail As TextBox = phUserCreate.Controls(0).Controls(7).FindControl("txtEmail")
lblText.Text = txtEmail.Text
So clearly .NET maintains the relationship between the control and the input tag that gets sent to and from the client and I hadn't yet crossed this leap of intuition.
Now I'm just wondering if there isn't some easier way to get to these values!
Thanks for the help folks, your guidance just helped me improve my understanding of .NET
Best Wishes,
Paul
http://www.thewebsiteshop.co.uk
|
|

April 4th, 2007, 07:27 AM
|
 |
Friend of Wrox
|
|
Join Date: Aug 2003
Posts: 5,407
Thanks: 0
Thanked 16 Times in 16 Posts
|
|
Yes, this is a much easier way.
First, add a public property to your user control that exposes the text property of the email textbox:
Code:
Public ReadOnly Property Email As String
Get
Return txtEmail.Text
End Get
End Property
Now you should be able to access that property directly off the user control:
(Note that I'm not sure what the type is of your user control. The file is "UserControl" so I'll assume the class type is also "UserControl", although this is not good practice as the class name "UserControl" is more than ambiguous. Just notice the conversion in the first line below, that's the key.)
Code:
Dim myUserControl As UserControl = CType(LoadControl("UserControl.ascx"), UserControl)
' Add the control to the place holder
Me.phUserCreate.Controls.Add(myUserControl)
Response.Write(myUserControl.Email) 'pulls the email textbox .Text value
Response.End()
- Peter
|
|
 |