开发者

When is Control.UniqueId created?

Does anybody know when a control's UniqueId is assigned?

Right now I've got some code in my Page_Init that is based off the UniqueId. However, depending on some business logic, I might need to rearrange the control hierarchy of the page before this happens.

So, my main question is, When is the UniqueId assigned? Is it possible for me to rearrange the hierarchy in Page_PreInit() so t开发者_StackOverflowhat when my code fires in Page_Init(), I'll have the proper UniqueId's assigned?


To answer this question, I wrote a small code-behind that logs the values for the UniqueID property for a 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 Visual Studio's Immediate Window to print out the logged 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 appears that the UniqueID was set to the string "MyControl" (which was in fact the ID property that I had specified for the control in the ASPX mark-up) for each of the events. It would seem that @Rewinder's answer from MSDN is correct. These are set before any of the ASP.NET page-level events are triggered.

EDIT:

If we look at the .NET 3.5 reference source (http://referencesource.microsoft.com/) for System.Web.UI.Control, we can see that the return value of UniqueID is computed 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, the below method is called when the naming container changes. The ClearCachedUniqueIDRecursive method resets the value of the _cachedUniqueID field so that it is regenerated on the next call to the UniqueID property.

private void UpdateNamingContainer(Control namingContainer) {
    // Remove the cached uniqueID if the control already had a namingcontainer
    // and the namingcontainer is changed. 
    if (_namingContainer != null && _namingContainer != namingContainer) {
        ClearCachedUniqueIDRecursive(); 
    } 

    _namingContainer = namingContainer; 
}


Is it possible for me to rearrange the hierarchy in Page_PreInit() so that when my code fires in Page_Init(), I'll have the proper UniqueId's assigned?

I can't tell exactly what you are trying to do, but it sounds like Microsoft discourages it:

Typically, you will not need to use the UniqueID property. For example, you should not write code that references controls by using a predicted value of the generated UniqueID property. You can read and pass the value of the UniqueID property to other processes, but you should not rely on it having a specific structure.


From MSDN:

This identifier is generated automatically when a page request is processed.

So Yes, you have access to the uniqueId during PreInit

EDIT

Ok, I guess I was a bit vague. Page.ProcessRequest calls the FrameworkInitialize() method, which will build the Control tree. This happens before PreInit, therefore the control's UniqueId is available.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜