为了回答这个问题,我编写了一个小的代码后台,记录了每个事件中控件唯一ID属性的值:
- PreInit
- Init
- InitComplete
- PreLoad
- Load
- LoadComplete
- PreRender
- PreRenderComplete
例如,最后一个事件处理程序如下:
protected void Page_PreRenderComplete(object sender, EventArgs e)
{
_uniqueIdValues.Add(
new Tuple<string, string>("PreRenderComplete", MyControl.UniqueID));
}
然后,我在卸载事件中设置了一个断点,并使用Visual Studio的Immediate窗口打印出记录的值:
_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属性)。似乎@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 (_id == null) {
GenerateAutomaticID();
}
if (Page == namingContainer) {
_cachedUniqueID = _id;
}
else {
string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();
if (uniqueIDPrefix.Length == 0) {
return _id;
}
else {
_cachedUniqueID = uniqueIDPrefix + _id;
}
}
return _cachedUniqueID;
}
else {
return _id;
}
}
}
当命名容器发生变化时,会调用以下方法。ClearCachedUniqueIDRecursive方法会重置_cachedUniqueID字段的值,以便在下一次调用UniqueID属性时重新生成它。
private void UpdateNamingContainer(Control namingContainer) {
if (_namingContainer != null && _namingContainer != namingContainer) {
ClearCachedUniqueIDRecursive();
}
_namingContainer = namingContainer;
}
UniqueId
-Tag
不是更好吗? - Daniel A. White