Control.UniqueId 何时创建?

Posted

技术标签:

【中文标题】Control.UniqueId 何时创建?【英文标题】:When is Control.UniqueId created? 【发布时间】:2011-07-25 06:41:05 【问题描述】:

有人知道何时分配控件的 UniqueId 吗?

现在我的 Page_Init 中有一些基于 UniqueId 的代码。但是,根据某些业务逻辑,我可能需要在此之前重新排列页面的控制层次结构。

所以,我的主要问题是,UniqueId 是什么时候分配的?我是否可以重新排列 Page_PreInit() 中的层次结构,以便当我的代码在 Page_Init() 中触发时,我将分配正确的 UniqueId?

【问题讨论】:

你为什么要依赖UniqueId - Tag 不是更好吗? 【参考方案1】:

为了回答这个问题,我编写了一个小代码隐藏,用于记录每个事件的控件的 UniqueID 属性的值:

预初始化 初始化 初始化完成 预加载 加载 加载完成 预渲染 预渲染完成

例如,最后一个事件处理程序如下所示:

protected void Page_PreRenderComplete(object sender, EventArgs e)

    _uniqueIdValues.Add(
        new Tuple<string, string>("PreRenderComplete", MyControl.UniqueID));

然后,我在 Unload 事件中设置了一个断点,并使用 Visual Studio 的即时窗口打印出记录的值:

_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)

似乎每个事件的 UniqueID 都设置为字符串“MyControl”(实际上是我在 ASPX 标记中为控件指定的 ID 属性)。 MSDN 中@Rewinder 的回答似乎是正确的。这些是在触发任何 ASP.NET 页面级事件之前设置的。

编辑:

如果我们查看 System.Web.UI.Control 的 .NET 3.5 参考源 (http://referencesource.microsoft.com/),我们可以看到 UniqueID 的返回值是在访问属性时计算的. UniqueID 属性如下所示:

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;
        
     

并且,当命名容器发生变化时,会调用下面的方法。 ClearCachedUniqueIDRecursive 方法重置 _cachedUniqueID 字段的值,以便在下次调用 UniqueID 属性时重新生成。

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; 

【讨论】:

有趣的是,如果我检查控件的 UniqueID 的值,然后更改该控件的父容器,当我再次检查 UniqueID 时,它会更新为新的层次结构。 查看 System.Web.UI.Control 的 .NET 参考源 (referencesource.microsoft.com)。 UniqueID 的返回值是在访问属性时计算的。如果 NamingContainer 发生更改,则 UniqueID 的内部缓存值将被重置,以便在下次访问该属性时重新计算。 我更新了我的答案以包含一些来自 .NET 3.5 参考源的代码。【参考方案2】:

我是否可以重新排列 Page_PreInit() 中的层次结构,以便当我的代码在 Page_Init() 中触发时,我将分配正确的 UniqueId?

我不能确切地知道你想要做什么,但听起来微软不鼓励这样做:

通常,您不需要使用 UniqueID 属性。例如, 你不应该写这样的代码 通过使用引用控件 生成的预测值 UniqueID 属性。你可以阅读和 传递 UniqueID 的值 其他进程的财产,但你 不应该依赖它有一个 具体结构。

【讨论】:

【参考方案3】:

来自MSDN:

生成此标识符 页面请求时自动 已处理。

所以是的,您可以在 PreInit 期间访问 uniqueId

编辑

好吧,我想我有点含糊。 Page.ProcessRequest 调用 FrameworkInitialize() 方法,该方法将构建控制树。这发生在 PreInit 之前,因此控件的 UniqueId 可用。

【讨论】:

在请求过程中发生了大量的事情,我建议发帖人知道这一点,并询问在请求过程中具体是在哪里为属性赋予了价值? 您的回答就像将出生描述为“婴儿从母亲的身体里出来”。是的,它是正确的,但它是如此模糊,以至于信息没有用。

以上是关于Control.UniqueId 何时创建?的主要内容,如果未能解决你的问题,请参考以下文章

uni-gram 何时比 bi-gram(或更高的 N-gram)更合适?

在 Python 中,我如何知道一个进程何时完成?

学习uni-app 第二步 认识uni-app/创建使用uni-app

uni-app快速上手

01uni-app的创建 运行在不同端上的配置 tarBar的配置

uni-app下使用vant组件