asp.net building controls:
I would like to know more about how the ASPNET runtime assigns unique control IDs to the controls on a page. I'm curious because it doesn't appear to be "fixed"...which causes problems with composite controls which contain controls doing postbacks. Here's what happened to me: I have a textbox and a button that are part of a composite control (StepControl) that is, in turn, part of another composite control (DynamicSelector). I create all the child controls in the exact same sequence every time (I've been burned with ViewState problems if I don't do that, so it's a habit). The command event from the button should cause a search activity to take place using th contents of the textbox. But what I found was that I had to enter the text and click the button twice (i.e., on two separate roundtrips) in order for the action to occur. Out of curiousity I tweaked the "outer" composite control, DynamicSelector, to always call the postback data handling mechanism (i.e., always call the interface IPostBackDataHandler). I then watched the contents of the ViewState bag. On the first postback, which did not involve the button or the textbox, each was assigned a particular control ID. But on the first search attempt (i.e., the first time I clicked the search button) each was assigned a >>different<< control ID. Of course, nothing happened, because the ASPNET runtime tried to wire up the postback data to the old IDs. Then, on the second button click, because the same/new control IDs were assigned, the action occurred. I "solved" this problem by assigning my own unique control IDs to the button and the textbox. But that strikes me as something I shouldn't have to do (and I can tell you it was very frustrating trying to figure this out, because the underlying problem is rather obscure). I did some further work and built a routine which "walked the control tree" for DynamicSelector and dumped all the control IDs and control Types to a file. When I did that, even without me assigning my own unique IDS, the problem disappeared -- which makes me suspect the IDs get assigned when the controls are "touched", and because my control tree walker always touched them in the same sequence it reported the same IDs...and maybe the internal mechanism for assigning IDs >>isn't<< "fixed"?
Okay, thanks. It still seems odd that the default ID assigner gives different results depending upon end-user interaction with the page.
Hello Mark, As for ASP.NET server control, both "ClientID" and "UniqueID" are generated based on the "ID" property. And the naming convention is also related to the position of the server control on page. It is when the server control being added into Page's control hierarchy, will its ClientID and UniqueID be finally determined. This because all the namingContainer(from control's directly parent container to top level container under page)'s ID will be embeded into server control's final "ClientID" and "UniqueID" Therefore, when you create server control in code(create dynamic controls in page) or create child controls in custom webserver control, you're recommended to manually assign a fixed ID for each control and add them into a parent container. If you want to register some script that will manipulate the certain controls at client-side, it would be better you do the script registering at "PreRender" event. Because at that time, all the controls has been added into Page's control hierarchy, and their clientID and UniqueID won't change further. Sincerely, Steven Cheng Microsoft MSDN Online Support Lead This posting is provided "AS IS" with no warranties, and confers no rights.
Thanks for your reply Mark, Actually, the automatic ID generation mainly depend on the number of controls exists in Parent namingContainer. ======reflector code================== private void GenerateAutomaticID() { this.flags.Set(0x200000); this._namingContainer.EnsureOccasionalFields(); int num1 = this._namingContainer._occasionalFields.NamedControlsID++; if (this.EnableLegacyRendering) { this._id = "_ctl" + num1.ToString(NumberFormatInfo.InvariantInfo); } else if (num1 < 0x80) { this._id = Control.automaticIDs[num1]; } else { this._id = "ctl" + num1.ToString(NumberFormatInfo.InvariantInfo); } this._namingContainer.DirtyNameTable(); } ============================= Sincerely, Steven Cheng Microsoft MSDN Online Support Lead This posting is provided "AS IS" with no warranties, and confers no rights.
Don't see what you're looking for? Try a search.
|