转摘自:http://hi.baidu.com/xiaobai0119/blog/item/52ed29dc129ed6a4cc116611.html

ASP.NET网页上的每一个控件都必须是可唯一标识的。通常,为控件的 ID 属性分配一个值来唯一标识该控件。该值将成为控件的实例名称(即,在代码中引用控件所依据的名称)。例如,如果将 TextBox 控件的 ID 属性设置为 Text1,则可以在代码中使用 Text1 来引用该控件。

许多数据绑定控件(包括 DataList、Repeater、GridView、FormView 和 DetailsView 控件)可作为其他(子)控件的容器。当这些控件运行时,它们会生成子控件的多个实例。例如,如果创建一个包含 Label 控件的 DataList 模板,则当页运行时,DataList 控件的数据源中包含多少个记录,就会在页中生成多少个该 Label 控件的实例。

注意
使用模板的控件(例如 DataList 和 Repeater 控件)承载模板对象。例如,当 DataList 控件运行时,它会创建 DataListItem 类的多个实例。而这些模板对象又包含单个控件,例如,标签、文本框、按钮,等等。

由于控件可在同一页上多次实例化,而且您可以在不同的页上重复使用控件名称,所以,ASP.NET 页框架提供了确保页上和应用程序中控件具有唯一标识符的机制。它还为您提供了找到这些单个控件的方法,以便您可以在自己的代码中操作它们。

命名容器
可作为其他控件的容器的控件会为其子控件生成“命名容器”或 ID 命名空间。通过提供此命名容器,控件可以保证其子控件的 ID 属性在整个应用程序内是唯一的。(控件通过实现 INamingContainer 接口来生成命名容器。)如果在运行时创建了子控件,命名容器将与子控件的 ID 属性进行组合,以创建每个子控件的 UniqueID 属性值。因此,UniqueID 属性会成为控件的完全限定标识符,引用其命名容器以及控件的各个 ID 值。

在上面的示例中,在父级 DataList 控件的命名容器(即命名空间)内创建 Label 控件的多个实例。每个 Label 控件的 UniqueID 属性将反映此命名空间,其格式类似于 DataList1:_ctl:MyLabel、DataList1:_ct2:MyLabel,依此类推。

注意
请不要编写使用生成的 UniqueID 属性的值引用控件的代码。可以将 UniqueID 属性视为一个句柄(例如,通过将它传递到进程),但不应指望它拥有特定结构。

每个容器控件都会为其子控件提供命名容器,此外,页本身也会为容器控件的所有子控件提供命名容器。这样,就可以在应用程序内为该页上的所有控件创建唯一的命名空间。

使用 NamingContainer 属性
子控件可以通过 NamingContainer 属性引用其命名容器。此属性会返回一个 Control 类型的对象,您可以将该对象强制转换为相应的 DataList 控件、DataListItem 对象等。

在需要从子控件访问容器控件的属性时,引用命名容器是很有用的。例如,在子控件的 DataBinding 事件的处理程序中,可以通过从命名容器获取 DataItem 对象来访问该对象。

注意
NamingContainer 属性和 Parent 属性引用的控件不必相同。例如,在 Repeater 控件中,可能有一个包含表的项模板,而该表又包含 Label 控件。标签的父级控件是表单元格(例如,HtmlTableCell 对象),但其命名容器是 DataListItem 对象,因为它是定义 Label 控件的命名空间的 DataListItem,而不是该表。

引用控件
如果页中包含在运行时生成的控件,例如,位于 DataList、Repeater 或 GridView 控件的模板中的控件,就不能直接按 ID 来引用这些控件,因为 ID 不是唯一的。但是,有多种方式可以找到页中的各个控件。

Web 窗体控件 ID 解析

当您声明 Web 服务器控件的 ID 属性以通过编程方式访问该控件时,ASP.NET 页框架将自动确保声明的 ID 在整个 ASP.NET Web 应用程序中是唯一的。

命名容器
ASP.NET 页框架通过 INamingContainer 接口为应用程序提供自动控件 ID 解决方案,该接口为实现它的每个类生成一个“命名容器”。命名容器在 ASP.NET 网页控件层次结构中定义一个新的 ID 命名空间。这样,命名容器便允许页框架为在该命名空间内生成的每个 Control 对象的 UniqueID 属性生成一个值。UniqueID 属性不同于您声明的 ID 属性,因为它是控件的完全限定标识符。

实现 INamingContainer 的类包括:Page、DataList、GridView、DataListItem、DataGridItem 和 Repeater。通常,可以创建子控件的那些控件都会动态实现 INamingContainer。

Page 类充当该页的控件层次结构中的顶级命名容器。

数据绑定方案中的名称解析
页框架提供的自动名称解决方案在数据绑定方案中很重要。请考虑下面的示例,该示例演示页中声明的控件。

当 Label 控件绑定到数据源,而 Repeater 控件循环访问该数据源中的项时,该页必须能够以编程的方式区分 Label 控件的不同实例,即使您只为每个实例指定了 ID MyLabel 也是如此。页框架通过对每个控件使用完全限定的 UniqueID 属性来实现这一点。例如,下面的代码生成了 Label 控件的三个版本,并将它们的 UniqueID 属性值写入该页。

当请求此页时,它将下面的内容写入该页:

名为 MyDataList 的 Repeater 控件的命名容器。此命名容器取决于指定给 .aspx 文件的名称。

注意
如果此示例的 .aspx 文件是 MySample1.aspx,则命名容器的类是 ASP.mysample1_aspx,但命名容器是 Page。

充当命名容器的下一个控件的实例,即 Repeater 控件。此容器的名称是随同它的整个命名空间限定符一起显示的。

Repeater 控件内每个 Label 控件的 UniqueID 属性。

注意
请不要编写使用生成的 UniqueID 属性的值引用控件的代码。可以将 UniqueID 属性视为一个句柄(例如,通过将它传递到进程),但不应指望它拥有特定结构。

如何在 ASP.NET 网页中按 ID 定位子控件

可以用一个方法来获取对特定控件的引用,该方法按控件 ID 搜索其命名容器。

按 ID 定位控件
调用命名容器的 FindControl 方法,向该方法传递包含要使用的控件的 ID 的字符串。该方法会返回一个类型为 Control 的对象,可以将该类型强制转换为适当的类型。

下面的代码示例演示如何定位特定的控件。该示例是 GridView 控件中某按钮的 Click 事件的处理程序。单击该按钮时,代码在当前的 GridView 项(它是 Label 控件的命名容器)中搜索名为 Label1 的控件。如果找到该控件,其文本便会显示在页面其他位置上第二个名为 LabelText 的 Label 控件中。
C#
protected void GridView1_ItemCommand(object source,
        GridViewCommandEventArgs e)
{
    Label l;
    l = (Label) e.Item.FindControl("Label1");
   
    if(!(l == null) ){
        LabelText.Text = l.Text;
    }
}

在 ASP.NET 网页中使用控件集合

    Control 类及其派生类(包括 Page 类)会公开一个返回 ControlCollection 的 Controls 属性。通过这种层次结构,可以通过编程方式对控件树进行遍历以搜索某页上的特定控件,并检查集合中的控件类型,以便访问其属性。下面的代码示例演示如何通过遍历该页的控件层次结构来查找 <asp:TextBox> 控件的实例(只有一个)。

如何通过遍历控件集合定位页上的 Web 窗体控件

在 Controls 集合中定位控件
依次通过容器控件的 Controls 集合。该集合的类型为 ControlCollection,它返回 Control 类型的对象。

下面的示例说明如何浏览 Controls 集合。该示例假定 ASP.NET 网页上至少有一个 TextBox 控件,还包含一个 Label 控件和一个 Button 控件。该代码会获取 Page 对象的所有子控件。由于这样只会产生几个高级别子控件(包括 HtmlForm 对象),所以该代码还要浏览每个单独的子控件的 Controls 集合。该代码会通过比较每个控件的类型来查找文本框。当它找到文本框时,它会获取该文本框的值并将该值串联成字符串,该字符串会显示在 Label 控件的末尾。

此示例只查找 Page 对象中包含的控件以及作为该页的直接子级的控件。如果文本框是控件的子级,而该控件又是页的子级,则该示例不查找此文本框。例如,如果您向该页中添加了 Panel 控件,则 Panel 控件将是包含在 Page 中的 HtmlForm 控件的子级,在此示例中可以找到该控件。然而,如果您之后将某个 TextBox 控件添加到 Panel 控件中,则此示例将不显示该 TextBox 控件的文本,因为该控件既不是页的子级,也不是页的子控件的子级。以这种方式浏览控件有一种更实用的方法:即创建递归方法。一遇到某个控件,就可调用该方法来浏览该控件的 Controls 集合。然而,为清楚起见,没有将下面的示例创建为递归函数。

使用 NamingContainer 属性确定控件的命名容器

通过 NamingContainer 属性,可以遍历某页中的控件树。与只在内联代码(即位于<%# 和 %> 标记中)中可用的 Container 关键字相比,NamingContainer 属性在该类或派生类的任何实例代码中可用。

下面的代码示例阐释了如何遍历 ASP.NET 网页中的控件树。按钮的 ChangeBtn_Click 方法处理程序首先使用 FindControl 方法搜索控件,然后确定该控件的 NamingContainer 对象。此后,它会确定首次调用 NamingContainer 属性时返回的控件的命名容器,然后会遍历控件树,直到找到不包含命名容器的控件为止。(请注意,WalkContainers 方法还将在最低级别添加控件的类型,该类型本身不是命名容器。)

如何访问 Web 服务器控件的命名容器的成员

有时,您需要访问控件的命名容器的属性或方法。例如,在数据绑定期间,命名容器可以提供包含控件所绑定的数据的 DataItem 属性。您可以根据上下文,采用不同方式来访问该包含控件。

从数据绑定表达式访问命名容器
在数据绑定表达式中,使用 Container 关键字。该关键字可以返回指向容器的引用。然后,可以访问容器的属性或方法。

在 Eval 方法中,经常使用此关键字获取命名容器的 DataItem 对象值;不过,也可以在该方法之外使用此关键字。下面的示例演示 Label 控件。该控件可能位于 DataList、Repeater 或 GridView 控件的模板中。该控件显示当前项的编号。

下面是一个类似的示例,不同之处在于从命名容器的 DataItem 对象中获取值:

注意
NamingContainer 属性和 Parent 属性引用的控件不必相同。例如,在 Repeater 控件中,可能有一个包含表的项模板,而该表又包含 Label 控件。标签的父级控件是表单元格(例如,HtmlTableCell 对象),但其命名容器是 DataListItem 对象,因为它是定义 Label 控件的命名空间的 DataListItem,而不是该表。

从代码访问命名容器
获取控件的 NamingContainer 属性,并将其强制转换为容器的类类型,如 GridViewRow。

有关使用 NamingContainer 属性获取各个控件命名容器方面的信息的示例,请参见使用 NamingContainer 属性确定控件的命名容器。

    Conctrol,Controls,DataItem这三者之间的联系与区分要重点学习。

    基于对.net的控件访问的理解还不是很透彻,现将MSDN中部分内容找出,希望对自己的学习有帮助。学习了一遍,对有些地方还不是很明白,以后慢慢研读吧。

posted on 2008-09-26 15:33  啊凡  阅读(444)  评论(0编辑  收藏  举报