最近使用GridView做报表时遇到一个问题,在老大帮助下完成。现在记录一下。
项目需求类似如下的嵌套:
(例如一个借还系统,父级是借设备人的资料,子级是具体设备资料)
-------------------------
父编号 姓名 年龄
1 张三 20
----------------
子编号 产品类型 产品名称
1 路由器 凌凯
----------------
2 李四 24
--------------------------
1.在一级数据的列数固定的情况下可直接使用如下嵌套:
基本思路是在行绑定事件中绑定嵌套的GridView2,这里如果GrideView2是动态列也可以,后台也能动态添加进去。
前台:
代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->< asp:GridView ID ="GridView1" runat ="server" AutoGenerateColumns ="false" onrowdatabound ="GridView1_RowDataBound" > < Columns > < asp:TemplateField HeaderText ="编号" > < ItemTemplate > <% # Eval ( " id " ) %> ItemTemplate > asp:TemplateField > < asp:TemplateField HeaderText ="姓名" > < ItemTemplate > <% # Eval ( " name " ) %> ItemTemplate > asp:TemplateField > < asp:TemplateField HeaderText ="年龄" > < ItemTemplate > <% # Eval ( " age " ) %> ItemTemplate > asp:TemplateField > < asp:TemplateField > < ItemTemplate >
< tr colspan ="3" > < asp:GridView ID ="GridView2" runat ="server" AutoGenerateColumns ="false" > < Columns > < asp:TemplateField HeaderText ="编号" > < ItemTemplate > <% # Eval ( " id " ) %> ItemTemplate > asp:TemplateField > < asp:TemplateField HeaderText ="类型" > < ItemTemplate > <% # Eval ( " type " ) %> ItemTemplate > asp:TemplateField > < asp:TemplateField HeaderText ="名称" > < ItemTemplate > <% # Eval ( " name " ) %> ItemTemplate > asp:TemplateField > Columns > asp:GridView >
tr > ItemTemplate > asp:TemplateField > Columns > asp:GridView >
后台:
代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->protected void Page_Load( object sender, EventArgs e) { DataTable dt = new DataTable(); dt.Columns.Add( " id " ); dt.Columns.Add( " name " ); dt.Columns.Add( " age " ); for ( int i = 0 ; i < 3 ;i ++ ) { dt.Rows.Add(i.ToString(), " 用户 " + i, 20 + i); } DataSet ds = new DataSet(); ds.Tables.Add(dt); this .GridView1.DataSource = ds; this .GridView1.DataBind(); } protected void GridView1_RowDataBound( object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { GridView gv = e.Row.FindControl( " GridView2 " ) as GridView; DataTable dt = new DataTable(); dt.Columns.Add( " id " ); dt.Columns.Add( " name " ); dt.Columns.Add( " type " ); for ( int i = 0 ; i < 3 ; i ++ ) { dt.Rows.Add(i.ToString(), " 产品 " + i, " 产品 " + i); } DataSet ds = new DataSet(); ds.Tables.Add(dt); gv.DataSource = ds; gv.DataBind(); } }
2,一级数据的行中含有动态列
开始考虑是动态的加列就可以了,我们在Page_Load事件中增加下面代码:
代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> for ( int i = 0 ; i < 2 ;i ++ )//向模板列中插入几列 { BoundField bf = new BoundField(); bf.HeaderText = " 测试 " + i; bf.DataField = " name " ; this .GridView1.Columns.Insert( 1 ,bf); }
编号
测试1
测试0
姓名
年龄
0
用户0
用户0
用户0
20
此时动态列增加上了,但是分页时在行绑定事件中已经找不到嵌套的GridView2了,原因我现在还不知道,请知道的朋友告知一下。
编号
类型
名称
0
产品0
产品0
1
产品1
产品1
2
产品2
产品2
1 用户1 用户1 用户1 21
编号
类型
名称
0
产品0
产品0
1
产品1
产品1
2
产品2
产品2
于是,到这里就想到自己写一个模板类了,控制更好一些,在写的过程中老大给了帮助,模板如下
代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->#region MyTemplate /// /// MyTemplate 的摘要说明 /// public class MyTemplate : ITemplate { private DataControlRowType dataControlRowType; private string dataField; public string DataField { get { return dataField; } set { dataField = value; } } private string columnName; public string ColumnName { get { return columnName; } set { columnName = value; } } private string controlID; public string ControlID { get { return controlID; } set { controlID = value; } } private bool isGrid; public bool IsGrid { get { return isGrid; } set { isGrid = value; } } public MyTemplate( string columnName) { dataControlRowType = DataControlRowType.Header; this .columnName = columnName; } public MyTemplate( string controlID, string dataField, bool isGrid) { dataControlRowType = DataControlRowType.DataRow; this .dataField = dataField; this .controlID = controlID; this .isGrid = isGrid; } #region ITemplate 成员 JXSoft.TicketManage.BLL.TicketTypeBLL ticketTypeBLL = new JXSoft.TicketManage.BLL.TicketTypeBLL(); void ITemplate.InstantiateIn(Control container) { switch (dataControlRowType) { case DataControlRowType.Header: Literal l = new Literal(); l.Text = ColumnName; container.Controls.Add(l); break ; case DataControlRowType.DataRow: if ( ! isGrid) { Label lbl = new Label(); lbl.ID = ControlID; lbl.DataBinding += new EventHandler(lbl_DataBinding); container.Controls.Add(lbl); } else { Label lbl = new Label(); lbl.ID = ControlID; lbl.DataBinding += new EventHandler(lbl_DataBinding); container.Controls.Add(lbl); #region 添加GridView 及内部绑定列 GridView gv = new GridView(); gv.ID = " GridView2 " ; gv.AutoGenerateColumns = false ; BoundField bf; bf = new BoundField(); bf.HeaderText = " 编号 " ; bf.DataField = " id " ; gv.Columns.Add(bf); bf = new BoundField(); bf.HeaderText = " 类型 " ; bf.DataField = " type " ; gv.Columns.Add(bf); bf = new BoundField(); bf.HeaderText = " 名称 " ; bf.DataField = " name " ; gv.Columns.Add(bf); TableRow trow = new TableRow(); TableCell cell = new TableCell(); cell.ColumnSpan = 3 ; cell.Controls.Add(gv); trow.Cells.Add(cell); container.Controls.Add(trow); #endregion } break ; default : break ; } } void lbl_DataBinding( object sender, EventArgs e) { Label lbl = sender as Label; GridViewRow gr = lbl.NamingContainer as GridViewRow; lbl.Text = DataBinder.Eval(gr.DataItem, DataField).ToString(); } #endregion } #endregion
也就是说我们可以在后台将所有的模板列动态的添加进GridView1
代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> TemplateField tf; tf = new TemplateField(); tf.HeaderTemplate = new MyTemplate( " 编号 " ); tf.ItemTemplate = new MyTemplate( " lblId " , " id " , false ); GridView1.Columns.Add(tf); tf = new TemplateField(); tf.HeaderTemplate = new MyTemplate( " 姓名 " ); tf.ItemTemplate = new MyTemplate( " lblName " , " name " , false ); GridView1.Columns.Add(tf); tf = new TemplateField(); tf.HeaderTemplate = new MyTemplate( " 年龄 " ); tf.ItemTemplate = new MyTemplate( " lblAge " , " age " , false ); GridView1.Columns.Add(tf); tf = new TemplateField(); tf.HeaderTemplate = new MyTemplate( "" ); tf.ItemTemplate = new MyTemplate( " GridView1 " , " age " , true ); GridView1.Columns.Add(tf);
接下来就可以在行绑定事件中找到GridView2并绑定数据了。分页也没问题。
当然也可以顺利导出。导出需要加以下代码:
代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> protected void btnExport_Click( object sender, EventArgs e) { this .GridView1.AllowPaging = false ; BindDetailReportToGv(); Response.Clear(); Response.AddHeader( " content-disposition " , " attachment;filename=DetailsLog.xls " ); Response.ContentType = " application/vnd.xls " ; System.IO.StringWriter sw = new System.IO.StringWriter(); System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(sw); this .GridView1.RenderControl(htmlWrite); Response.Write(sw.ToString()); Response.End(); this .GridView1.AllowPaging = true ; } public override void VerifyRenderingInServerForm(Control control) { // Confirms that an HtmlForm control is rendered for }
其实解决这个问题应该还有更好的办法,关键在于2点:
第一个问题是如果一级数据中有动态列,那么分页时的行绑定事件内找不到行里的GridView2,
第二个问题是导出数据时由于采用colspan=“100%”,页面看上去是嵌套了,但是导出为excel后布局就会乱了。
您有更好的办法吗,欢迎交流。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-659739/
,如需转载,请注明出处,否则将追究法律责任。