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

动态加载用户控件的时候,会因为调用一些控件的一些属性和方法而造成控件命名混乱.
因为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生成原理

public virtual string ClientID

{

    get

    {

        this.EnsureID();

        string uniqueID = this.UniqueID;

        if ((uniqueID != null) && (uniqueID.IndexOf(this.IdSeparator) >= 0))

        {

            return uniqueID.Replace(this.IdSeparator, '_');

        }

        return uniqueID;

    }

}

protected void EnsureID()

{

    if (this._namingContainer != null)

    {

        if (this._id == null)

        {

            this.GenerateAutomaticID();

        }

        this.flags.Set(0x800);

    }

}

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

public virtual string UniqueID

{

    get

    {

        if (this._cachedUniqueID == null)

        {

            Control namingContainer = this.NamingContainer;

            if (namingContainer == null)

            {

                return this._id;

            }

            if (this._id == null)

            {

                this.GenerateAutomaticID();

            }

            if (this.Page == namingContainer)

            {

                this._cachedUniqueID = this._id;

            }

            else

            {

                string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();

                if (uniqueIDPrefix.Length == 0)

                {

                    return this._id;

                }

                this._cachedUniqueID = uniqueIDPrefix + this._id;

            }

        }

        return this._cachedUniqueID;

    }

}

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等

转:服务器控件的 ID,ClientID,UniqueID 的区别的更多相关文章

  1. asp.net 服务器控件的 ID,ClientID,UniqueID 的区别

    1.简述 ID是设计的时候自己所指定的ID,是我们分配给服务器控件的编程标识符,我们常常使用this.controlid来寻找控件,那么这个controlid就是这里所说的ID. ClientID是由 ...

  2. id,clientid 和 uniqueid 的区别

    一. ID是设计的时候所指定的ID. ClientID是当这个控件生成到客户端页面时候,需要在客户端访问时候用的. UniqueID是当需要参与服务端回传的时候用的. 备注:当控件是子控件的时候(例如 ...

  3. 当使用母版页时JavaScript客户端获取服务器控件的Id

    当使用MasterPage.UserControl等容器时,为了避免控件的重复命名,asp.net会自动将容器中的控件生成一个ClientID(Control Tree中的可生成,否则不会生成). J ...

  4. html元素中id和name的区别

    可以说几乎每个做过Web开发的人都问过,到底元素的ID和Name有什么区别阿?为什么有了ID还要有Name呢?! 而同样我们也可以得到最classical的答案:ID就像是一个人的身份证号码,而Nam ...

  5. html中元素的id和name的区别(2016-1-22)

    HTML中元素的Id和Name属性区别 一直以来一直以为在html中,name和id没什么区别,今天遇到一个坑才发现(PHP获取不到表单数据,原因:元素没有name,只定义了id),这两者差别还是很大 ...

  6. form表单中的id 与name的区别

    以前经常写form表单时,不写id和name,总觉得没有什么用.后来一看后台套完的页面发现,他们都补上name,不知道所以然,就查了一下资料,吓我一跳,要是照我那样写根本不会有数据传到服务器.原来表单 ...

  7. javascript querySelector和getElementById通过id获取元素的区别

    querySelector和getElementById通过id获取元素的区别 <!DOCTYPE html> <html> <head> <meta cha ...

  8. id和class的区别

    id和class是定义css样式用到的,不同的是定义样式时的写法不一样,使用id选择样式时,定义的格式为 #main{width:20px;} ,使用class时用到的是 .main{width:20 ...

  9. form表单中id与name的区别

    以前经常写form表单时,不写id和name,总觉得没有什么用.后来一看后台套完的页面发现,他们都补上name,不知道所以然,就查了一下资料,吓我一跳,要是照我那样写根本不会有数据传到服务器.原来表单 ...

随机推荐

  1. cf卡中,wtmp文件较大,导致磁盘空间满了

    看了一下,有一个wtmp 和wtmp.1的文件非常大.wtmp记录的是机器注销.启动的信息.由此可见,机器长时间的不断重启,造成该日志记录超级大,把cf的空间给占满了. wtmp日志可以用who和la ...

  2. 在 Ubuntu 上配置高性能的 HHVM 环境

    HHVM全称为 HipHop Virtual Machine,它是一个开源虚拟机,用来运行由 Hack(一种编程语言)和 PHP 开发应用.HHVM 在保证了 PHP 程序员最关注的高灵活性的要求下, ...

  3. [Js]弹性运动

    描述:像弹簧一样左右弹动,最后缓慢停下来 一.加减速运动 1.加速运动 var iSpeed=0;iSpeed++; 速度越来越快,最后冲出去 2.减速运动 var iSpeed=20;iSpeed- ...

  4. "琳琅满屋"调查问卷 心得体会及结果分析

    ·关于心得体会       当时小组提出这个校园二手交易市场的时候,就确定了对象范围,仅仅是面向在校大学生,而且在我们之前就已经有了很多成功的商品交易的例子可以让我们去借鉴,再加上我们或多或少的有过网 ...

  5. C#操作Access数据库(创建&修改结构)

    本文转自:http://www.cnblogs.com/liyugang/archive/2012/11/17/2775393.html 想要在程序中控制Access,不是数据,而是Access数据库 ...

  6. CodeForces 540C Program D

    Description You play a computer game. Your character stands on some level of a multilevel ice cave. ...

  7. MicroPython开发板TPYBoard关于USB-HID的应用

    USB-HID是Human Interface Device的缩写,属于人机交互操作的设备,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球.电话拨号设备.VCR遥控等等设备. ...

  8. SharePoint表单和工作流 - Nintex篇(七)

    博客地址 http://blog.csdn.net/foxdave 接上篇点击打开链接 在工作流设计面板点击Close返回到列表页面,切换到List标签,选择"Nintex Forms&qu ...

  9. 《c语言全局变量的用法》

    //全局变量的用法. /*有一个一维数组,内放n个学生的成绩,(n由用户自己指定,通过调用函数实现定义一个数组.)写一个函数,当主函数调用此函数后,能求出平均分,最高分,最低分.*/ #include ...

  10. sql server手工注入

    sql server手工注入 测试网站testasp.vulnweb.com 1. http://testasp.vulnweb.com/showforum.asp?id=0 http://testa ...