Asp.Net控件的客户端命名

时间:2023-03-09 18:49:36
Asp.Net控件的客户端命名

我们在用ASP.NET写出来的网页,用浏览器来查看生成的客户端代码的时候经常看到这样的代码:GridView1_ctl101_WebUserControl1_webuserControlButton,那么这个命名有什么规律,是怎么来的拉?本次我们使用Reflector查看.net的代码研究其中的规律。

我们的ASP.NET服务器端控件在生成客户端控件的时候一般有id 和name两个属性,这两个属性我们在服务器端可以通过ClientID和UniqueID来得到。
以一个Button为例,用Reflector打开System.Web.dll,找到System.Web.UI.WebControls命名空间下面的Button类,我们可以发现该类继承至WebControl类,其实大多数控件都继承至这个类。这个类是继承了System.Web.UI.Control类的,这个类是我们要研究的重点,该类继承至System.Object类,这是所有类的基类,我们就不去研究了,接下来我们来看看Control类。
找到Control类下面的ClientID属性,查看其代码如下:

Asp.Net控件的客户端命名public virtual string ClientID
Asp.Net控件的客户端命名{
Asp.Net控件的客户端命名    get
Asp.Net控件的客户端命名    {
Asp.Net控件的客户端命名        this.EnsureID();
Asp.Net控件的客户端命名        string uniqueID = this.UniqueID;
Asp.Net控件的客户端命名        if ((uniqueID != null) && (uniqueID.IndexOf(this.IdSeparator) >= 0))
Asp.Net控件的客户端命名        {
Asp.Net控件的客户端命名            return uniqueID.Replace(this.IdSeparator, '_');
Asp.Net控件的客户端命名        }
Asp.Net控件的客户端命名        return uniqueID;
Asp.Net控件的客户端命名    }
Asp.Net控件的客户端命名}

也就是说ClientID就是将UniqueID中的IdSeparator (其值为:”$”)替换为”_”。比如我们写一个页面生成出来的代码如下:
<input type="submit" name="GridView1$ctl101$WebUserControl1$webuserControlButton" value="Button" id="GridView1_ctl101_WebUserControl1_webuserControlButton" />
显然name和id的不同就是将其中$替换为了_。
现在ClientID我们已经清楚了,那么UniqueID又是怎么生成的拉?让我们用Reflector来看看。

Asp.Net控件的客户端命名public virtual string UniqueID
Asp.Net控件的客户端命名{
Asp.Net控件的客户端命名    get
Asp.Net控件的客户端命名    {
Asp.Net控件的客户端命名        if (this._cachedUniqueID == null)
Asp.Net控件的客户端命名        {
Asp.Net控件的客户端命名            Control namingContainer = this.NamingContainer;//获得父控件
Asp.Net控件的客户端命名            if (namingContainer == null)
Asp.Net控件的客户端命名            {
Asp.Net控件的客户端命名                return this._id;
Asp.Net控件的客户端命名            }
Asp.Net控件的客户端命名            if (this._id == null)
Asp.Net控件的客户端命名            {
Asp.Net控件的客户端命名                this.GenerateAutomaticID();//对控件自动编号
Asp.Net控件的客户端命名            }
Asp.Net控件的客户端命名            if (this.Page == namingContainer)//当前控件的父控件是Page则UniqueID就是控件的ID。
Asp.Net控件的客户端命名            {
Asp.Net控件的客户端命名                this._cachedUniqueID = this._id;
Asp.Net控件的客户端命名            }
Asp.Net控件的客户端命名            else//当前控件父控件是另一种容器控件
Asp.Net控件的客户端命名            {
Asp.Net控件的客户端命名                string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();//取得父控件UniqueID+分隔符($)作为当前控件的UniqueID前缀。
Asp.Net控件的客户端命名                if (uniqueIDPrefix.Length == 0)
Asp.Net控件的客户端命名                {
Asp.Net控件的客户端命名                    return this._id;
Asp.Net控件的客户端命名                }
Asp.Net控件的客户端命名                this._cachedUniqueID = uniqueIDPrefix + this._id;//前缀+ID 作为当前控件的UniqueID
Asp.Net控件的客户端命名            }
Asp.Net控件的客户端命名        }
Asp.Net控件的客户端命名        return this._cachedUniqueID;
Asp.Net控件的客户端命名    }
Asp.Net控件的客户端命名}
Asp.Net控件的客户端命名

这段代码中,最重要的就是GenerateAutomaticID()函数和namingContainer.GetUniqueIDPrefix();函数。我们可以跟进去看看函数是如何实现的。

Asp.Net控件的客户端命名private void GenerateAutomaticID()
Asp.Net控件的客户端命名{
Asp.Net控件的客户端命名    this.flags.Set(0x200000);
Asp.Net控件的客户端命名    this._namingContainer.EnsureOccasionalFields();
Asp.Net控件的客户端命名    int index = this._namingContainer._occasionalFields.NamedControlsID++;
Asp.Net控件的客户端命名    if (this.EnableLegacyRendering)
Asp.Net控件的客户端命名    {
Asp.Net控件的客户端命名        this._id = "_ctl" + index.ToString(NumberFormatInfo.InvariantInfo);
Asp.Net控件的客户端命名    }
Asp.Net控件的客户端命名    else if (index < 0x80)
Asp.Net控件的客户端命名    {
Asp.Net控件的客户端命名        this._id = automaticIDs[index];
Asp.Net控件的客户端命名    }
Asp.Net控件的客户端命名    else
Asp.Net控件的客户端命名    {
Asp.Net控件的客户端命名        this._id = "ctl" + index.ToString(NumberFormatInfo.InvariantInfo);
Asp.Net控件的客户端命名    }
Asp.Net控件的客户端命名    this._namingContainer.DirtyNameTable();
Asp.Net控件的客户端命名}
Asp.Net控件的客户端命名

从这个函数我们可以看出,对于像GridView这种绑定控件,其生成的每一行中的控件名是由ctl+自增的数字组成的。其中数字的格式化是两位数字,也就是说不足两位的时候补零,多出两位就按实际内容算。

Asp.Net控件的客户端命名internal virtual string GetUniqueIDPrefix()
Asp.Net控件的客户端命名{
Asp.Net控件的客户端命名    this.EnsureOccasionalFields();
Asp.Net控件的客户端命名    if (this._occasionalFields.UniqueIDPrefix == null)
Asp.Net控件的客户端命名    {
Asp.Net控件的客户端命名        string uniqueID = this.UniqueID;
Asp.Net控件的客户端命名        if (!string.IsNullOrEmpty(uniqueID))
Asp.Net控件的客户端命名        {
Asp.Net控件的客户端命名            this._occasionalFields.UniqueIDPrefix = uniqueID + this.IdSeparator;
Asp.Net控件的客户端命名        }
Asp.Net控件的客户端命名        else
Asp.Net控件的客户端命名        {
Asp.Net控件的客户端命名            this._occasionalFields.UniqueIDPrefix = string.Empty;
Asp.Net控件的客户端命名        }
Asp.Net控件的客户端命名    }
Asp.Net控件的客户端命名    return this._occasionalFields.UniqueIDPrefix;
Asp.Net控件的客户端命名}
Asp.Net控件的客户端命名

这个函数返回父控件的UniqueID+IdSeparator,如果父控件UniqueID为空,那么就返回空。
现在我们再回过头来看看GridView1$ctl101$WebUserControl1$webuserControlButton这命名:从中我们可以看到这是一个GridView控件下面绑定了一个WebUserControl控件,而这个控件中有一个webuserControlButton控件。Asp.Net控件的客户端命名