原贴子在这里:http://www.tiantiansoft.com/bbs/dispbbs.asp?boardID=40&ID=90981
相关贴子在这里:http://www.tiantiansoft.com/bbs/dispbbs.asp?boardID=40&ID=91023
嗯,我是在Repeater1里,套了一个Repeater2,然后在Repeater2里,套了两个DataGrid,一共嵌套是三层。用Repeater1套Repeater2,是为了搞分组的显示,在Repeater2里套DataGrid,是想要给明细记录显示其它具体的信息。
在aspx页面里,我是这样子定义的:
<asp:repeater id="Repeater1" runat="server">
<HeaderTemplate>
<table width="600" border="1" align="center">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td colspan="11">分组报头信息<asp:TextBox ID="MyId" CssClass="hiddeninput" Runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "d_iid") %>'></asp:TextBox></td>
</tr>
<asp:Repeater id="Repeater2" runat="server" OnItemCommand="Repeater2_ItemCommand" OnItemDataBound="Repeater2_ItemDataBound">
<ItemTemplate>
<tr align="center">
<td>这个按钮就是我想要用来控制两个DataGrid的显示的按钮
<asp:imagebutton id="Detail" CommandName="detail" CausesValidation="False" runat="server" ImageUrl="../images/plus.gif"></asp:imagebutton><asp:TextBox ID="txtPid" Runat="server" CssClass="hiddeninput" Text='<%# DataBinder.Eval(Container.DataItem,"pid") %>'></asp:TextBox>
</td>
<tr align="center">
<td colspan="8">
<asp:DataGrid id="DataGrid1" runat="server" Width="570px" AutoGenerateColumns="False">
</asp:DataGrid>
<asp:DataGrid id="DataGrid2" runat="server" Width="570px" AutoGenerateColumns="False">
</asp:DataGrid>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:repeater>
这里的东东,是我把所有具体信息都删除掉了的,只留下了有关的控件的相互关系的框架。
嗯,蓝色那一段,是很重要的。因为被嵌套的控件的数据的检索,是要在父级控件的ItemDataBound事件里检索的,可是被嵌套的控件在页面里是没有定义的,他们要在父级控件里用FindControl来取,所以他们的事件也要在程序里动态的绑定。关于On...这个,我在MSDN里查到的是“引发事件时会通过委托调用事件处理程序”,可是具体是嘛样子搞法的,我也没知道。我本来是在Repeater1的ItemDataBound事件里使用下面的语句来委托的:
MyRepeater.ItemDataBound+=new System.Web.UI.WebControls.RepeaterItemEventHandler(this.Repeater2_ItemDataBound);
MyRepeater.ItemCommand += new System.Web.UI.WebControls.RepeaterCommandEventHandler(this.Repeater2_ItemCommand);
但建立委托后,ItemCommand事件还是没法使用,所以我只好使用了OnItemCommand和OnItemDataBound,让他们自己搞。
下边看.cs文件,Repeater1的DataBind可以写在需要的地方,这里主要想说的是Repeater2和两个DataGrid的数据的检索,还有就是通过按钮控制DataGrid的属性
1、检索第二层的Repeater2:在Repeater1的ItemDataBound事件里绑定数据:
private void Repeater1_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
//检索具体项目
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Repeater MyRepeater=(Repeater)e.Item.FindControl("Repeater2");
if(MyRepeater!=null)
{
string diid,mysql;
TextBox MyTextBox=(TextBox)e.Item.FindControl("MyId");
if(MyLabel!=null)
{
diid=MyTextBox.Text.Trim();
mysql="这里是检索数据时用的sql语句";
mysql+=" from 表名 where d_iid=" + diid;
//检索,我这里是把所有东东都提到NNLL.cs文件里的,所以直接调用里面的方法
NNLL nnll=new NNLL();
SqlConnection MyConnection=nnll.OpenConn();
nnll.Repeater_Retrieve(this,MyConnection,MyRepeater,mysql);
nnll.CloseConn(MyConnection);
}
}
}
}
因为Repeater2是用来显示Repeater1中每一条记录所对应的明细记录的,所以它需要从Repeater1里取条件,我在Repeater1里用了一个id=MyId的TextBox记录值,取值方法如红色那几段
2、检索第二层的两个DataGrid,在aspx页面里,已经定义了OnItemDataBound="Repeater2_ItemDataBound,所以这里只需要自定义Repeater2_ItemDataBound方法。嗯,这两个DataGrid,是用来显示明细项的具体其它信息的,所以同样要从当前的明细项里取条件,我用在Repeater2里加了一个id=txtPid的TextBox
protected void Repeater2_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//嵌套子Repeater的ItemDataBound事件
TextBox MyTextBox=(TextBox)e.Item.FindControl("txtPid");
string pid=null;
if(MyTextBox!=null)
{
pid=MyTextBox.Text.Trim();
//参与人员
DataGrid MyDataGrid=(DataGrid)e.Item.FindControl("DataGrid1");
if(MyDataGrid!=null) DataGrid_Retrieve(MyDataGrid,"boffin",pid);
//文件
MyDataGrid=(DataGrid)e.Item.FindControl("DataGrid2");
if(MyDataGrid!=null) DataGrid_Retrieve(MyDataGrid,"file",pid);
}
}
}
这里我用的是private,因为这个方法我要在aspx页面里调用
3、在第二层的Repeater2里,用按钮控制两个DataGrid的Visible属性。在aspx页面里,已经定义了OnItemCommand="Repeater2_ItemCommand",这里也是再自定义一个Repeater2_ItemCommand方法就成:
protected void Repeater2_ItemCommand(object source, System.Web.UI.WebControls.RepeaterCommandEventArgs e)
{
//嵌套子Repeater的ItemCommand事件
if(e.CommandName=="detail")
{
//检索DataGrid
DataGrid MyDataGrid=null;
Repeater MyRepeater=null;
MyRepeater=(Repeater)source;
if(MyRepeater!=null)
{
MyDataGrid=(DataGrid)MyRepeater.Items[e.Item.ItemIndex].FindControl("DataGrid1");
MyDataGrid.Visible=!(MyDataGrid.Visible);
MyDataGrid=(DataGrid)MyRepeater.Items[e.Item.ItemIndex].FindControl("DataGrid2");
MyDataGrid.Visible=!(MyDataGrid.Visible);
}
}
}
使用事件自己的source参数,可以直接调用当前点击的按钮所在的Repeater控件,所以可以直接用它使用FindControl来取第三层的DataGrid
最后,嗯,我自己的总结就是,嗯,嵌套是没嘛关系的,我现在还没试过,我是想,如果我在第三层的DataGrid里也使用OnItemDataBound="DataGrid1_ItemDataBound"的话呢,应该也可以在第三层的DataGrid里搞一个模版列,再套第四层的其它数据控件,然后呢,用DataGrid1_ItemDataBound事件来检索它的。不过有个问题是,数据库在这里,虽然是一个页面,不过是没断的给打开又关闭的,每一层嵌套的控件检索数据时,都需要在它的父级的ItemDataBound事件里再连接一回数据库。
嗯,我的意思,呀,嘛样子表达好呢?
这样子来说,Repeater1里套着Repeater2的,在检索Repeater1的数据时,数据库是已经连接了的,而ItemDataBound事件呢,是每个Item都触发的,在Repeater1里显示了几条记录,ItemDataBound事件就被触发几回,那就相当于有几个Repeater2被检索过数据,而Repeater2检索时,又要再连接一回数据库,这里连接的数据库就是重复的了,对服务器来说是负担加重了。
剩下的是搞完后才发现这里没嘛东东技巧,用的就是事件的委托、FindControl还有ItemCommand事件的第一个参数object source,如果这些东东在一开始的时候就掌握好了的话呢,就用没着耗上我这么这么多的时间来搞了