To answer this question, I wrote a little code that records the values of the UniqueID property for the control for each of these events:
- Preinit
- Init
- Initcomplete
- Preload
- Load
- Loadcomplete
- Prerender
- PreRenderComplete
The last event handler, for example, looked like this:
protected void Page_PreRenderComplete(object sender, EventArgs e) { _uniqueIdValues.Add( new Tuple<string, string>("PreRenderComplete", MyControl.UniqueID)); }
Then I set a breakpoint in the Unload event and used the Visual Studio Immediate window to print the registered values:
_uniqueIdValues.ToArray() {System.Tuple<string,string>[8]} [0]: {(PreInit, MyControl)} [1]: {(Init, MyControl)} [2]: {(InitComplete, MyControl)} [3]: {(PreLoad, MyControl)} [4]: {(Load, MyControl)} [5]: {(LoadComplete, MyControl)} [6]: {(PreRender, MyControl)} [7]: {(PreRenderComplete, MyControl)}
It looks like UniqueID was set to the “MyControl” line (which was actually the ID property that I specified for the control in the ASPX label) for each of the events. It would seem that @Rewinder's answer from MSDN is correct. They are set before any of the events are triggered at the page level of ASP.NET.
EDIT:
If we look at the source source of .NET 3.5 (http://referencesource.microsoft.com/) for System.Web.UI.Control, we see that the return value of UniqueID is calculated when the property is accessed. The UniqueID property looks like this:
public virtual string UniqueID { get { if (_cachedUniqueID != null) { return _cachedUniqueID; } Control namingContainer = NamingContainer; if (namingContainer != null) { // if the ID is null at this point, we need to have one created and the control added to the // naming container. if (_id == null) { GenerateAutomaticID(); } if (Page == namingContainer) { _cachedUniqueID = _id; } else { string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix(); if (uniqueIDPrefix.Length == 0) { // In this case, it is probably a naming container that is not sited, so we don't want to cache it return _id; } else { _cachedUniqueID = uniqueIDPrefix + _id; } } return _cachedUniqueID; } else { // no naming container return _id; } } }
And this method is called when the naming container changes. The ClearCachedUniqueIDRecursive method resets the value of the _cachedUniqueID field so that it is restored the next time the UniqueID property is called.
private void UpdateNamingContainer(Control namingContainer) {