HQT

追求.NET 技术永无止境

导航

实现 DataGrid 在打印时,每页都可显示 表头

Posted on 2005-09-14 13:27  HQT  阅读(1077)  评论(2编辑  收藏  举报


MS 的DataGrid 在数据呈现上非常好用,可在WEB打印时,无法在分页时每页都能显示表头,造成诸多不便。
经过一段时间的研究和资料搜索,找到一种解决办法:

要使打印时,每页都可显示表头,需要将 table 改造成 thead ,tbody,tfoot 分组。
现改造如下:

在WEB 应用程序项目中添加 WEB自定义控件,
代码如下:
其中的 namespace 名改为你当前项目的 namespace

namespace FullDataGridControl
{
    
using System;
    
using System.Data;
    
using System.Drawing;
    
using System.Web;
    
using System.Web.UI.WebControls;
    
using System.Web.UI.HtmlControls;
    
using System.IO;
    
using System.Web.UI;

    
/// <summary>
    
///        FullDataGrid 的摘要说明。
    
/// </summary>

    public class FullDataGrid : System.Web.UI.WebControls.DataGrid
    
{
        
protected override void Render(System.Web.UI.HtmlTextWriter writer)
        
{
            writer.Write(
this.ParsMarkupWithPrintStyle(ParseMarkup()));
        }

        
/// <summary>
        
/// 去除 table 的 border 和  rules
        
/// </summary>
        
/// <param name="oldMarkup"></param>
        
/// <returns></returns>

        private string ParsMarkupWithPrintStyle(string markup)
        
{            

            markup 
= markup.Replace("<td","<td  style=\"BORDER-RIGHT:black 1px  solid;BORDER-TOP:black 1px  solid;BORDER-LEFT:black 1px  solid;BORDER-BOTTOM:black 1px  solid\"");
            
            markup 
= markup.Replace("rules=\"all\"","");
            markup 
= markup.Replace("border=\"1\"","border=\"0\"");

            
return markup;
        }

        
/// <summary>
        
/// 插入 thead,tbody 元素
        
/// </summary>
        
/// <returns></returns>

        private string ParseMarkup()
        
{
            StringWriter writer 
= new StringWriter();
            HtmlTextWriter buffer  
= new HtmlTextWriter(writer);
            
base.Render(buffer);
            
            
string markup = writer.ToString() ;
            
            
// <THEAD> 标签的位置 插在第一个 > 之后,即 <table> 之后
            int theadStarPos = markup.IndexOf(">")+">".Length;            
                        
            markup 
= markup.Insert(theadStarPos,"<thead style=\"DISPLAY:table-header-group;\">");
            
            
// </THEAD><TBODY> 标签的位置, 插在第一个 </tr> 之后
            int theadEndPos = markup.IndexOf("</tr>")+"</tr>".Length;    
            
            markup 
= markup.Insert(theadEndPos,"</thead><tbody>");
            
            
// </TBODY> 插在原先的 </TABLE> 之前
            int tbodyEndPos = markup.IndexOf("</table>");                
            
            markup 
= markup.Insert(tbodyEndPos,"</tbody><TFOOT style=\"DISPLAY: table-footer-group; FONT-WEIGHT: bold\">"+
                            
"<tr><TD style=\"BORDER-TOP:black 1px  solid\""+
                            
" ></TD></TR></TFOOT>");
            
return markup;
        }

    }

}

 
简单改造完毕。

为何要去掉 原来系统自动生成的 rules="all" 而且将 border=1 改为0 呢?
rules="all" 表示全部显示线框(上下左右)
如果不去掉,在打印第一页之后的页面时,表头的顶部线条会消失,效果自然不理想。
所以干脆去掉原先表格的线条,自己添加每个 td 的 border . 也就是这行:

markup = markup.Replace("<td","<td  style=\"BORDER-RIGHT:black 1px  solid;BORDER-TOP:black 1px  solid;BORDER-LEFT:black 1px  solid;BORDER-BOTTOM:black 1px  solid\"");
            




现做测试:

添加一个 WEBFORM,名为 FullDataGridTest.aspx
HTML 页代码如下:

<%@ Register TagPrefix="FullDataGridControl" Assembly="FullDataGridControl" Namespace="FullDataGridControl"%>
<%@ Page language="c#" Codebehind="FullDataGridTest.aspx.cs" AutoEventWireup="false" Inherits="FullDataGridControl.FullDataGridTest" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
    
<HEAD>
        
<title>FullDataGridTest</title>
        
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        
<meta content="C#" name="CODE_LANGUAGE">
        
<meta content="JavaScript" name="vs_defaultClientScript">
        
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
        
<style media="print">
        .noprint
{display:none;}
        }
        .nextpage 
{
    PAGE-BREAK-AFTER
: always
}

        
</style>
    
</HEAD>
    
<body MS_POSITIONING="GridLayout">
        
<form id="Form1" method="post" runat="server">
            
<FullDataGridControl:FullDataGrid id="FullDataGrid1" runat="Server">
            
</FullDataGridControl:FullDataGrid>
            
</form>
    
</body>
</HTML>

HTML代码很简单,只是要注意下 style media="print" ,该样式只在打印时有用。
noprint 即不打印输出, nextpage 为分页点

后台 cs  代码如下:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace FullDataGridControl
{
    
/// <summary>
    
/// FullDataGridTest 的摘要说明。
    
/// </summary>

    public class FullDataGridTest : System.Web.UI.Page
    
{
        
protected FullDataGrid FullDataGrid1;

        
private void Page_Load(object sender, System.EventArgs e)
        
{
            
string[] strArr = new string[80];
            
for(int i=0;i<strArr.Length;i++)
            
{
                strArr[i] 
= "a";
                
            }


            FullDataGrid1.DataSource 
= strArr;
            FullDataGrid1.DataBind();
            
            
for(int i=30;i<FullDataGrid1.Items.Count;i+=30)
            
{
                FullDataGrid1.Items[i].CssClass 
= "nextpage";
            }

        }


        
#region Web 窗体设计器生成的代码
        
override protected void OnInit(EventArgs e)
        
{
            
//
            
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
            
//
            InitializeComponent();
            
base.OnInit(e);
        }

        
        
/// <summary>
        
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
        
/// 此方法的内容。
        
/// </summary>

        private void InitializeComponent()
        
{    
            
this.Load += new System.EventHandler(this.Page_Load);
        }

        
#endregion

    }

}