您的位置:首页 > 其它

如何更好的理解控件的层次关系

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: