如何更好的理解控件的层次关系
2007-09-12 22:25
211 查看
今天做项目,在做到dataGrid嵌套dataGrid时,做成了二个模板列,在用FindControl()时,却找不到对应名字的控件。其实还是没有弄清楚理解里面的层次关系。
偶尔想起网上看到的一篇博客调用一个方法可以解决这个问题,与大家分享一下。
大部分ASP.NET控件都实现INamingContainer接口,包括 DataGrid,
Repeater, 和 the DataList.
下例是建一个带有DataGrid的form 。以HTML格式输出.
<form id="Form1" method="post"
runat="server">
<asp:DataGrid
id=DataGrid1 runat="server" DataSource="<%# employees1
%>"
AutoGenerateColumns="False"
OnSelectedIndexChanged="DataGrid1_SelectedIndexChanged"
OnEditCommand="DataGrid1_EditCommand">
<Columns>
<asp:BoundColumn DataField="emp_id"
SortExpression="emp_id" HeaderText="emp_id"/>
<asp:BoundColumn DataField="fname"
SortExpression="fname" HeaderText="fname"/>
<asp:BoundColumn
DataField="lname" SortExpression="lname"
HeaderText="lname"/>
<asp:TemplateColumn>
<ItemTemplate>
<asp:TextBox Runat="server" ID="TextBox1" />
</ItemTemplate>
</asp:TemplateColumn>
<asp:ButtonColumn
Text="Select"
CommandName="Select"></asp:ButtonColumn>
<asp:EditCommandColumn ButtonType="LinkButton"
UpdateText="Update"
CancelText="Cancel" EditText="Edit">
</asp:EditCommandColumn>
</Columns>
</asp:DataGrid>
</form>
form中的DataGird将从一个已知的table里显示数据。使用模板列,在DataGird的每一行增加一个带有ID的TextBox。下面是ASP.NET形成的HTML的内容(浏览器上的源文件):
<table cellspacing="0" rules="all"
border="1" id="DataGrid1">
<tr>
<td>emp_id</td><td>fname</td><td>lname</td><td> </td><td> </td><td> </td>
</tr>
<tr>
<td>A-C71970F</td><td>Aria</td><td>Cruz</td><td>
<input
name="DataGrid1:_ctl2:TextBox1" type="text"
id="DataGrid1__ctl2_TextBox1" />
</td><td>
</tr>
<tr>
<td>A-R89858F</td><td>Annette</td><td>Roulet</td><td>
<input
name="DataGrid1:_ctl3:TextBox1" type="text"
id="DataGrid1__ctl3_TextBox1" />
</td><td>
</tr>
public class FindUtil
{
public static
string DumpParents(Control c)
{
StringBuilder
sb = new StringBuilder();
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
while(c.Parent != null)
{
c =
c.Parent;
sb.Append(" -><br>");
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
}
return
sb.ToString();
}
}
这里我们可以看到有很多TextBox1的实例,但是每个ID都预先有增加一些的标识符信息的处理。这个行为是因为有INamingContainer在工作。DataGrid实现INamingContainer接口,并且以每个子控件的ID再加上DataGrid1来描述此控件。因此我们可以很马上看出来,DataGrid是使用一个DataGridItem集合控件来呈现每一行的数据。一个DataGridItem 控件也实现INamingContainer接口,用子控件的名字和它自己产生的标识符来描述自己(‘_ctrl2’,
‘_ctrl3’等等)。现在,如果我们使用如下的代码,FindControl将返回一个空值
Control c = Page.FindControl(“TextBox1”)
Page控件找不到TextBox1,因为TextBox控件把自己隐藏在INamingContainer控件集合中。另外,哪个控件是我们真正想要返回的控件呢?是页上的TextBox控件?最后的TextBox控件?有代表性的例子是,当你想要找到一个在DataGrid中TextBox,将会在客户已经选择的指定的行上找TextBox.例如:我们增加一个选择列来允许用户点击一个Hyperlink来选择已选择的列。让我们来试下捕获下TextBox控件SelectedIndexChanged事件吧
以下代码是在选择DataGridItem对象时调用FindControl方法
private void DataGrid1_SelectedIndexChanged(object
sender, System.EventArgs e)
{
TextBox b;
b =
DataGrid1.Items[DataGrid1.SelectedIndex].FindControl("TextBox1") as
TextBox;
if(b != null)
{
Response.Write("Sender = " + sender.GetType().ToString() +
"<br>");
Response.Write("Found
Textbox1 in
SelectedIndexChanged event<br>");
Response.Write(FindUtil.DumpParent(b));
}}
我们可以增加一些额外的输出来更清楚地看下TextBox的关系链。 TextBox1控件有个TableCell对象作为父控件,返回一个DataGridItem对象的子控件,这个链一直到Page控件。代码演示如下(运行结果见页末)
public class FindUtil
{
public static
string DumpParents(Control c)
{
StringBuilder
sb = new StringBuilder();
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
while(c.Parent != null)
{
c =
c.Parent;
sb.Append(" -><br>");
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
}
return
sb.ToString();
}
}
以上代码将使父类控件引用建立一个控件IDS的string对象(当一个控件ID存在---不是所有的在form中的控件都有一个服务端的ID)和控件类型
我们也可以增加一个EditCommandColumn在DataGrid中,便于用户选择一行来编辑。EditCommand event handler 是较简单的,因为第二个参数对于Handler来讲是DataGridCommandEventArgs类型,其包含一个用户已经选择的DataGridItem的引用。
protected void DataGrid1_EditCommand(object source,
DataGridCommandEventArgs e)
{
TextBox b;
b =
e.Item.FindControl("TextBox1") as TextBox;
if(b != null)
{
Response.Write("Found Textbox1
in EditCommand event<br>");
}
}
运行结果如下:
Sender = System.Web.UI.WebControls.DataGrid
Found TextBox1 in SelectedIndexChanged event
TestBox1(System.Web.UI.WebControls.TextBox)->
(System.Web.UI.WebControls.TableCell)->
(System.Web.UI.WebControls.DataGridItem)->
(System.Web.UI.WebControls.DataGridTable)->
DataGrid1(System.Web.UI.WebControls.DataGrid)->
Form1(System.Web.UI.HtmlControls.HtmlForm)->
(ASP.FindControl4pre_aspx)
英文网址如下:
http://www.odetocode.com/Articles/116.aspx
偶尔想起网上看到的一篇博客调用一个方法可以解决这个问题,与大家分享一下。
大部分ASP.NET控件都实现INamingContainer接口,包括 DataGrid,
Repeater, 和 the DataList.
下例是建一个带有DataGrid的form 。以HTML格式输出.
<form id="Form1" method="post"
runat="server">
<asp:DataGrid
id=DataGrid1 runat="server" DataSource="<%# employees1
%>"
AutoGenerateColumns="False"
OnSelectedIndexChanged="DataGrid1_SelectedIndexChanged"
OnEditCommand="DataGrid1_EditCommand">
<Columns>
<asp:BoundColumn DataField="emp_id"
SortExpression="emp_id" HeaderText="emp_id"/>
<asp:BoundColumn DataField="fname"
SortExpression="fname" HeaderText="fname"/>
<asp:BoundColumn
DataField="lname" SortExpression="lname"
HeaderText="lname"/>
<asp:TemplateColumn>
<ItemTemplate>
<asp:TextBox Runat="server" ID="TextBox1" />
</ItemTemplate>
</asp:TemplateColumn>
<asp:ButtonColumn
Text="Select"
CommandName="Select"></asp:ButtonColumn>
<asp:EditCommandColumn ButtonType="LinkButton"
UpdateText="Update"
CancelText="Cancel" EditText="Edit">
</asp:EditCommandColumn>
</Columns>
</asp:DataGrid>
</form>
form中的DataGird将从一个已知的table里显示数据。使用模板列,在DataGird的每一行增加一个带有ID的TextBox。下面是ASP.NET形成的HTML的内容(浏览器上的源文件):
<table cellspacing="0" rules="all"
border="1" id="DataGrid1">
<tr>
<td>emp_id</td><td>fname</td><td>lname</td><td> </td><td> </td><td> </td>
</tr>
<tr>
<td>A-C71970F</td><td>Aria</td><td>Cruz</td><td>
<input
name="DataGrid1:_ctl2:TextBox1" type="text"
id="DataGrid1__ctl2_TextBox1" />
</td><td>
</tr>
<tr>
<td>A-R89858F</td><td>Annette</td><td>Roulet</td><td>
<input
name="DataGrid1:_ctl3:TextBox1" type="text"
id="DataGrid1__ctl3_TextBox1" />
</td><td>
</tr>
public class FindUtil
{
public static
string DumpParents(Control c)
{
StringBuilder
sb = new StringBuilder();
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
while(c.Parent != null)
{
c =
c.Parent;
sb.Append(" -><br>");
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
}
return
sb.ToString();
}
}
这里我们可以看到有很多TextBox1的实例,但是每个ID都预先有增加一些的标识符信息的处理。这个行为是因为有INamingContainer在工作。DataGrid实现INamingContainer接口,并且以每个子控件的ID再加上DataGrid1来描述此控件。因此我们可以很马上看出来,DataGrid是使用一个DataGridItem集合控件来呈现每一行的数据。一个DataGridItem 控件也实现INamingContainer接口,用子控件的名字和它自己产生的标识符来描述自己(‘_ctrl2’,
‘_ctrl3’等等)。现在,如果我们使用如下的代码,FindControl将返回一个空值
Control c = Page.FindControl(“TextBox1”)
Page控件找不到TextBox1,因为TextBox控件把自己隐藏在INamingContainer控件集合中。另外,哪个控件是我们真正想要返回的控件呢?是页上的TextBox控件?最后的TextBox控件?有代表性的例子是,当你想要找到一个在DataGrid中TextBox,将会在客户已经选择的指定的行上找TextBox.例如:我们增加一个选择列来允许用户点击一个Hyperlink来选择已选择的列。让我们来试下捕获下TextBox控件SelectedIndexChanged事件吧
以下代码是在选择DataGridItem对象时调用FindControl方法
private void DataGrid1_SelectedIndexChanged(object
sender, System.EventArgs e)
{
TextBox b;
b =
DataGrid1.Items[DataGrid1.SelectedIndex].FindControl("TextBox1") as
TextBox;
if(b != null)
{
Response.Write("Sender = " + sender.GetType().ToString() +
"<br>");
Response.Write("Found
Textbox1 in
SelectedIndexChanged event<br>");
Response.Write(FindUtil.DumpParent(b));
}}
我们可以增加一些额外的输出来更清楚地看下TextBox的关系链。 TextBox1控件有个TableCell对象作为父控件,返回一个DataGridItem对象的子控件,这个链一直到Page控件。代码演示如下(运行结果见页末)
public class FindUtil
{
public static
string DumpParents(Control c)
{
StringBuilder
sb = new StringBuilder();
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
while(c.Parent != null)
{
c =
c.Parent;
sb.Append(" -><br>");
sb.Append(c.ID + " (" + c.GetType().ToString() +
")");
}
return
sb.ToString();
}
}
以上代码将使父类控件引用建立一个控件IDS的string对象(当一个控件ID存在---不是所有的在form中的控件都有一个服务端的ID)和控件类型
我们也可以增加一个EditCommandColumn在DataGrid中,便于用户选择一行来编辑。EditCommand event handler 是较简单的,因为第二个参数对于Handler来讲是DataGridCommandEventArgs类型,其包含一个用户已经选择的DataGridItem的引用。
protected void DataGrid1_EditCommand(object source,
DataGridCommandEventArgs e)
{
TextBox b;
b =
e.Item.FindControl("TextBox1") as TextBox;
if(b != null)
{
Response.Write("Found Textbox1
in EditCommand event<br>");
}
}
运行结果如下:
Sender = System.Web.UI.WebControls.DataGrid
Found TextBox1 in SelectedIndexChanged event
TestBox1(System.Web.UI.WebControls.TextBox)->
(System.Web.UI.WebControls.TableCell)->
(System.Web.UI.WebControls.DataGridItem)->
(System.Web.UI.WebControls.DataGridTable)->
DataGrid1(System.Web.UI.WebControls.DataGrid)->
Form1(System.Web.UI.HtmlControls.HtmlForm)->
(ASP.FindControl4pre_aspx)
英文网址如下:
http://www.odetocode.com/Articles/116.aspx
相关文章推荐
- [SQL Server]SQL Server中如何存储具有层次关系的表(转)
- 如何更好的理解js中的this,分享2段有意思的代码
- 要理解__doPostback函数的用法,首先我们要理解Asp.net 中服务端控件事件是如何触发的。 Asp.net 中在客户端触发服务端事件分为三种情况: 一. WebControls中
- 关于关系代数中除法的理解以及如何用基本运算表示除法
- 如何更好的理解IOC和AOP
- 如何理解VB窗体中的scale类属性及width height属性之间的关系
- 如何理解进程和页的关系???
- 关于dubbo的理解,使用,常见问题以及如何更好的实施服务化
- WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码
- [JAVA · 初级]:10.如何更好的理解多态
- 如何理解session和cookie的关系(例子那是相当的好理解),附带session共享
- 如何更好的使用SiteMapPath控件来导航站点
- SQL Server中如何存储具有层次关系的表
- 如何理解JavaScript、Java、Jsp、J2ee之间的关系与区别
- 如何理解Nginx, WSGI, Flask之间的关系
- WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码
- 如何理解session和cookie的关系(例子那是相当的好理解),附带session共享
- 如何有效理解Active Directory中的全局组合本地域的关系
- 页面如何协调其控件的关系问题
- 如何理解人工智能、机器学习和深度学习三者的关系