2011-03-29 88 views
4

有人知道控件的UniqueId何时分配吗?什么时候创建了Control.UniqueId?

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

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

+0

你为什么依赖于'UniqueId'''''''''''会更好吗? – 2011-03-29 13:01:56

回答

6

要回答这个问题,我写了一个小的代码隐藏记录的UniqueID属性的值对于这些事件的控制:

  • PreInit
  • 初始化
  • InitComplete
  • 预紧
  • 负载
  • LoadComplete
  • 的PreRender
  • PreRenderComplete

的最后一个事件处理程序,例如,是这样的:

protected void Page_PreRenderComplete(object sender, EventArgs e) 
{ 
    _uniqueIdValues.Add(
     new Tuple<string, string>("PreRenderComplete", MyControl.UniqueID)); 
} 

然后,我在卸载事件中设置一个断点,并使用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被设置为st为每个事件敲响“MyControl”(实际上是我为ASPX标记中的控件指定的ID属性)。似乎@ Rewinder从MSDN的答案是正确的。这些设置在触发任何ASP.NET页面级事件之前设置。

编辑:

如果我们看看.NET 3.5的参考源(http://referencesource.microsoft.com/)为System.Web.UI.Control,我们可以看到,返回值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; 
} 
+0

有趣的是,如果我检查控件的UniqueID的值,然后更改该控件的父容器,当我再次复检的UniqueID,它更新到新的层次。 – 2011-03-29 17:20:52

+0

看一看为System.Web.UI.Control的.NET参考源(http://referencesource.microsoft.com/)。当访问属性UniqueID的返回值进行计算。如果NamingContainer更改,则UniqueID的内部缓存值将被重置,以便在下次访问该属性时重新计算。 – 2011-03-30 11:25:08

+0

我更新了我的答案,以包含来自.NET 3.5参考资源的一些代码。 – 2011-03-30 11:34:46

0

MSDN来自:

该标识符生成 时自动页面请求是 处理。

所以是的,你PreInit

编辑过程中有机会获得UNIQUEID

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

+2

有一个请求时那张巨量,我提出了海报都知道,并问在哪里在请求过程中特别是财产被赋予它的价值? – 2011-03-29 13:02:33

+3

你的回答就像描述出生一样:“一个婴儿从母亲的身体中出来”。是的,这是正确的,但它是如此含糊以至于这些信息是没用的。 – FreeAsInBeer 2011-03-29 13:07:17

+0

基伦,这是正确的 – 2011-03-29 13:15:31

1

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

我不能告诉正是你正在尝试做的,但它听起来像微软鼓励它:

通常情况下,你不需要使用 UniqueID属性。例如, 您不应使用生成的 UniqueID属性的 预测值编写 引用控制的代码。您可以阅读并 将UniqueID 属性的值传递给其他进程,但您不应该依赖它具有 特定结构。

相关问题