Repeater控件是asp.net 2.0提供的一个模块化控件,主要用来借助DataBinder对内置数据进行绑定。实际的应用中很多情况下会有嵌套使用Repeater。下面的例子的场景也是笔者遇到的一个管理权限的实例。
实例的场景是这样的,要实现一个系统权限设置的页面。而数据库中与这部分有关的表有:User(用户)、Role(角色)、Operation(操作)、Permission(权限),各表之间的关系如下图所示。
如果对于一个给定的role_id和operation_id如果在Permission找不到相应的项,则等价于valid值为False。要将权限表实现在管理页面中,以一个表的形式显示,表格的列头为各种操作,而行头为各种角色,而中间各格为对应行角色的对应列操作是否可操作,以CheckBox的形式供页面访问者操作,效果如下图所示:
页面中嵌套使用Repeater的代码如下:
< HeaderTemplate >
< table id = " permission_table " border = " 1 " >
< tr >
< th ></ th >
< asp:Repeater ID = " Repeater2 " runat = " server " DataSourceID = " SqlDataSource2 " >
< ItemTemplate >
< th ><% # Eval( " Operation_name " ) %>
</ th >
</ ItemTemplate >
</ asp:Repeater >
</ tr >
</ HeaderTemplate >
< ItemTemplate >
< tr >
< th ><% # Eval( " Role_name " ) %>
</ th >
< asp:Repeater ID = " Repeater2 " runat = " server " DataSourceID = " SqlDataSource2 " OnItemDataBound = " rp2_ItemDataBound " >
< ItemTemplate >
< td >
< asp:CheckBox ID = " MyCheckBox " runat = " server " OnCheckedChanged = " Check_Changed " />
</ td >
</ ItemTemplate >
</ asp:Repeater >
</ tr >
</ ItemTemplate >
< FooterTemplate >
</ table >
< asp:Button ID = " Submit_Button " Text = " 提交 " runat = " server " OnClientClick = " return confirm('您是否确定要保存设置?') " OnCommand = " Button_Command " CommandName = " SubmitPermission " />
< asp:Button ID = " Reset_Button " Text = " 重置 " runat = " server " OnClientClick = " return confirm('您是否确定重置为上次设置?') " CommandName = " ResetPermission " />
</ FooterTemplate >
</ asp:Repeater >
以上代码中SqlDataSource1是选出了Role表中所有角色,而SqlDataSource2是选出了Operation表中所有操作。并可以通过调用业务逻辑层写好的函数GetAllPermission来获取Permission中所有项。然后要解决的问题就是要给每个CheckBox设定初始状态的Checked值。这里用到Repeater的OnItemDataBound事件处理函数。通过以下代码得到每个CheckBox对应的role_id和operation_id,进而得到数据库中对应的valid值,并将checked值设为valid。为每个CheckBox保存这三个属性,以便后面发生变化时,通过Check_changed事件将变化写回到数据库中。
... {
DataRowView drvrp1,drvrp2;
RepeaterItem rpitem;
CheckBox MyCheckBox;
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
...{
rpitem = (RepeaterItem)(((Repeater)sender).NamingContainer);
drvrp1 = (DataRowView)rpitem.DataItem;
drvrp2 = (DataRowView)e.Item.DataItem;
MyCheckBox = (CheckBox)e.Item.FindControl("MyCheckBox");
string role_id = drvrp1["Role_id"].ToString();
string operation_id = drvrp2["Operation_id"].ToString();
bool valid = PermissionSystem.GetPermission(Int32.Parse(role_id),Int32.Parse(operation_id));
MyCheckBox.Checked = valid;
MyCheckBox.Attributes.Add("role_id", role_id);
MyCheckBox.Attributes.Add("operation_id", operation_id);
MyCheckBox.Attributes.Add("Valid",valid.ToString());
}
}
以上代码中比较重要的其实主要是如何从内层的Repeater(即Repeater2)中访问到外层Repeater(即Repeater1)中的Role_id。这里用到内层Repeater的NamingContainer属性得到包含了它的外层Repeater的RepeaterItem,具体对这个例子来说就是得到了表格中这一行的标识,进而也就可以得到Role_id。
而对于如何保存修改,就是使用CheckBox的Check_Changed事件捕捉改变,然后把改变写回,而不需要将整个表都重新写回到数据库中。