zoukankan      html  css  js  c++  java
  • 转:服务器控件的 ID,ClientID,UniqueID 的区别

    动态加载用户控件的怪问题

    动态加载用户控件的时候,会因为调用一些控件的一些属性和方法而造成控件命名混乱.
    因为add 一个用户控件或者 loadcontrol 的时候
    如果没有指定控件的id,clientid,那么它会初始id为:"_ctl0"

    如果在把用户控件 add到页面之前调用了一下用户控件里面的 TextBox1.ClientID-->会导致用户控件开始命名
    因为这时候用户控件这时候还没有被add到页面,所以这时候生成的 ClientID 肯定不会有父控件的名称.
    而且子控件的初始id为:"_ctl0",接着往下,只要是没有被命名的 _ctl1,_ctl2......

    这样当用户控件真正的被 add到页面时 同样用户控件也没有指定控件的id,那么这个用户控件的 id就会被
    初始id为:"_ctl0"


    到这我们应该看出问题了.
    子控件与父控件的id重复了.从而导致了用户控件里面的 TextBox1 的viewstate 不能被恢复,按钮事件不能被触发等等一系列怪问题.
    而如果先把用户控件 add进入页面,然后再做操作.则用户控件里面的控件命名变为:

    用户控件   
    id            type
    _ctl0  ASP.webusercontrol1_ascx
    _ctl0:_ctl0
       System.Web.UI.LiteralControl
    _ctl0:Button2 System.Web.UI.WebControls.Button
    _ctl0:_ctl1 System.Web.UI.LiteralControl

    *********************************************************

    1简述

    ID是设计的时候所指定的ID。有我们在写代码的时候指定的.是我们分配给服务器控件的编程标识符。我们常常在服务器端使用方法findcontrol(controlid) 来寻找控件.这时候controlid指的就是这个ID.

    ClientID是由ASP.Net生成的服务器控件标识符,当这个控件生成到客户端页面时候,需要在客户端访问时候用的。 ClientID 通过将子控件的父控件的 UniqueID 值与控件的 ID 值连接生成,各个部分之间以下划线 _ 连接。

    如我们常常用到的js脚本:

    var searchID = '<%=btnSearch.ClientID%>';

        document.getElementById(searchID).click();

    获取btnSearch 的ClientID,在client中呈现为html元素的id属性

    UniqueID 服 务器控件的唯一的、分层的形式限定的标识符。 是当需要参与服务端回传的时候用的。当将控件放置到重复控件(Repeater、DataList和DataGrid)中时,将可能生成多个服务器端的控 件,这就需要区分服务器端的各个控件,以使它们的 ID 属性不冲突。UniqueID 通过将子控件的父控件的 UniqueID 值与控件的 ID 值连接生成,各个部分之间以 IdSeparator 属性指定的字符连接。默认情况下, IdSeparator 属性为冒号字符 (:)。此属性为在 .Net Framework2.0种新增加。  在client中呈现为html元素的name属性

    2生成原理

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩public virtual string ClientID

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    get

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        this.EnsureID();

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        string uniqueID = this.UniqueID;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        if ((uniqueID != null) && (uniqueID.IndexOf(this.IdSeparator) >= 0))

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            return uniqueID.Replace(this.IdSeparator, '_');

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        return uniqueID;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩}

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩protected void EnsureID()

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    if (this._namingContainer != null)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        if (this._id == null)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            this.GenerateAutomaticID();

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        this.flags.Set(0x800);

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩}

    ClientID就是将UniqueID中的IdSeparator 替换为”_”。

     

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩public virtual string UniqueID

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    get

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        if (this._cachedUniqueID == null)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            Control namingContainer = this.NamingContainer;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            if (namingContainer == null)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                return this._id;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            if (this._id == null)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                this.GenerateAutomaticID();

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            if (this.Page == namingContainer)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                this._cachedUniqueID = this._id;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            else

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                if (uniqueIDPrefix.Length == 0)

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩{

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                    return this._id;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩                this._cachedUniqueID = uniqueIDPrefix + this._id;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩            }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩        return this._cachedUniqueID;

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩    }

    服务器控件的 ID,ClientID,UniqueID 的区别 - 静水流深 - 彧轩}

    if (this._id == null)

    {

        this.GenerateAutomaticID();

    }

    //对控件编号初始化

    if (this.Page == namingContainer)

    {

         this._cachedUniqueID = this._id;

    }

    //当前控件的父控件是Page,如一些用户控件之类的,则它的UniqueID就是控件的ID。

    else

    {

          string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();

          if (uniqueIDPrefix.Length == 0)

          {

              return this._id;

          }

          this._cachedUniqueID = uniqueIDPrefix + this._id;//前缀+ID 作为当前控件的UniqueID

    }

    //当前控件父控件不是父控件而是像Repeater、DataList和DataGrid,已经table等的另一种容器控件

    //那我们先根据 GetUniqueIDPrefix() 方法 取得父控件UniqueID+分隔符($)作为当前控件的UniqueID前缀。

    //这里要注意的是如果这时候子控件还没有被add到父控件里面,或者父控件的ID还没有,那么它的UniqueID就是它本身的ID。有父控件就前缀加ID

    GenerateAutomaticID()

    private void GenerateAutomaticID()

    {

        this.flags.Set(0x200000);

        this._namingContainer.EnsureOccasionalFields();

        int index = this._namingContainer._occasionalFields.NamedControlsID++;

        if (this.EnableLegacyRendering)

        {

            this._id = "_ctl" + index.ToString(NumberFormatInfo.InvariantInfo);

        }

        else if (index < 0x80)

        {

            this._id = automaticIDs[index];

        }

        else

        {

            this._id = "ctl" + index.ToString(NumberFormatInfo.InvariantInfo);

        }

        this._namingContainer.DirtyNameTable();

    }

    //对控件编号初始化

    GetUniqueIDPrefix函数

    internal virtual string GetUniqueIDPrefix()

    {

        this.EnsureOccasionalFields();

        if (this._occasionalFields.UniqueIDPrefix == null)

        {

            string uniqueID = this.UniqueID;

            if (!string.IsNullOrEmpty(uniqueID))

            {

                this._occasionalFields.UniqueIDPrefix = uniqueID + this.IdSeparator;

            }

            else

            {

                this._occasionalFields.UniqueIDPrefix = string.Empty;

            }

        }

        return this._occasionalFields.UniqueIDPrefix;

    }

    3

    this.Controls.Add 这个方法对 UniqueID的影响.

    这时候控件会加上父控件的UniqueID.

    这个问题可以参照我

    动态加载用户控件的怪问题 http://www.cnblogs.com/kasafuma/archive/2008/04/09/1145390.html

    因为先在用户控件里面调用了 子控件的clientID, 这时候用户控件还没有被加到 页面.

    所以子控件的clientID 为clt0.而当用户控件被add到页面的时候它的ID又会被初始化为clt0,造成ID的重复.

    所以我们在添加用户控件时先add后再调用它里面的一些方法和属性.如clienID等

  • 相关阅读:
    redis系列(五):搭建redis-cluster集群
    redis系列(四):切换RDB备份到AOF备份
    python写一个随机点名软件
    java使用flink集成mybatis每五分钟实时计算小时内用户行为数据
    本地缓存google.guava及分布式缓存redis 随笔
    spring boot+spring security 使用随笔
    MVEL2.0的使用实例(一)
    springboot2.x优雅的整合mybatis
    Springboot全套技术培训和常用框架整合
    私有云篇-[1相关技术]
  • 原文地址:https://www.cnblogs.com/Unrmk-LingXing/p/4110843.html
Copyright © 2011-2022 走看看