control id and names are a mess because MS did not understand the W3C rules
when they wrote the code.
background.
html form controls have a name property that is used in a form post
<form><input name="myInput" type="button" value="foo"></form>
when posted the browser will send
myInput=foo
originally there were no rules for forming name. later version of html set
rules (use id rule - see below)
later version of html added the id attribute from xml. the id attribute has
many rules.
1) must be unique across the document
2) must start with a letter
3) can only contain letters, numbers and underscore
when ms wrote web controls they had the issue of naming nested controls. the
simple fix concat the names together with ":" between them. for example if
button1 was nested in control control1, the name would be
"control1:button1". this turned out to be a really bad decision. for several
reasons.
1) ":" are not allowed in the id attribute, so they are removed and replaced
with _
2) while non w3c compliant browser allowed the ":" in name, it lead to
scripting errors, because the name was not valid javascript name, so could
not be used in the common syntax:
document.forms[0].myFieldname
3) IE has a bug which causes an alert if a ":" is present in a url under
https. this caused problems with postback:
javascript:_doPostBack('control1:control2')
would cause an alert on an https page, so now __dopostback() replaces
the ":" with $.
javascript:_doPostBack('control1$control2')
4) the name attribute is the name the backend uses to match up the posted
data with the controls. the name still uses ":" even though some proxy
servers will strip it, and thus are not compatiable with .net
now:
ClientID is the name of the control on the server side, it does not have to
be unique. Two parent controls can controls of the same name, otherwise
writing composite controls would be hard.
UniqueID is the what the rendered html attribute id will be. this is what
your javascript should use and will contain the any parent container names.
in your web control you want to:
TextBox t=new TextBox;
t.ID = "X";
Control.Attributes["OnClick"] ="javascript:document.getElementById('"
+ this.FindControl("X").UniqueID + // get the unique id of my
child control X
+ "').value='test';";
assuming the webcontrol's id is TextBox1 (and is a div), when rendered it
looks like:
<div id="TextBox1"
OnClick="javascript:document.getElementById('TextBox1_X').value='test';" >
<input type=text id="TextBox1_X" name="TextBox1:X">
</div>
-- bruce (sqlwork.com)
kw said:
Guess what...it still doesn't work for me (I can see how this will work in
your example). And here's the funny thing: after the controls are added and
ClientID is known (even in OnPreRender)...the final HTML looks like this:
MyControl1_MyControl1__ctl16
instead of (from tb.ClientID)
_MyControl1__ctl16
I don't understand why ASP.NET is modifying the ID after OnPreRender.