偶尔想起网上看到的一篇博客调用一个方法可以解决这个问题,与大家分享一下。
大部分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事件吧
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