如何更好的理解控件的层次关系
偶尔想起网上看到的一篇博客调用一个方法可以解决这个问题,与大家分享一下。
大部分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>
<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-C
<input
name="DataGrid1:_ctl2:TextBox1" type="text"
id="DataGrid1__ctl2_TextBox1" />
</td><td>
</tr>
<tr>
<td>A-R
<input
name="DataGrid1:_ctl3:TextBox1" type="text"
id="DataGrid1__ctl3_TextBox1" />
</td><td>
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接口,用子控件的名字和它自己产生的标识符来描述自己(‘_ctrl
Control c = Page.FindControl(“TextBox
Page控件找不到TextBox
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
Textbox
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 Textbox
}
}
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