接到上面的order, 将DataGrid改写成表头固定, 而要带scroll bar滚动记录. 看了felix兄的文章
Fixed Header Scrollable DataGrid control
http://blog.joycode.com/felix/articles/32789.aspx
好像有点不太适合自己用. 他将Header截出来, 做成Div, 然后把原来的DataGrid Header盖住, 形成一种假象, 就像表头真的被固定了, 而且两者的位置好像对得不准, 新生成的Header有点左移(不知道是不是我机子的问题
). 后来按照我跟上司的设想, 因为DataGrid最终输出的是一个Table, 所以将这个Table拆分为三部份, Header, Items, Pager. 然后在Items外面加一个Div, 用javascript控制Div是否出现Scroll bar.BTW: 因为DataGrid我们是重新封装过的. 有部份代码只适合此Grid使用, 但万变不离其中. enjoy it .
/// <summary>
/// Author : Kenneth Lee
/// Create Date : 2004-11-8
/// Description : override Render方法, 在网格输出时, 修改网站的样式.
/// 将整个DataGrid划分为Headers, Items, Pager 三个表格, 利用Div的属性控制是否出现scroll bar.
/// 并且确保客户端调整控件其它样式时, 其样式保持不变.
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)
{
//确定DataGrid处于何种状态, 是运行时还是设计时
//Control.Site属性是获取控件当前站点的信息
bool gridDesignMode = ((Site != null) && (Site.DesignMode));
//只有运行时输出以下内容
if (!gridDesignMode)
{
// 将HTML转换为StringBuilder
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
//保证每列的宽度
Style["TABLE-LAYOUT"] = "fixed";
// 输出到sw中.
base.Render(htw);
StringBuilder sbRenderedTable = sw.GetStringBuilder();
htw.Close();
sw.Close();
string temp = sbRenderedTable.ToString();
if (sbRenderedTable.Length > 0)
{
if (this.HeaderText == string.Empty)
{
// 将DataGrid的ID替换为表头ID
sbRenderedTable.Replace(ID,ID + "_Headers", 0, (temp.IndexOf(ID) + ID.Length));
// 为保持表头和表脚的高度, 将height属性去掉.
sbRenderedTable.Remove(sbRenderedTable.ToString().ToLower().IndexOf("height:"), this.Height.ToString().Length+8);
temp = sbRenderedTable.ToString();
//找出表头的长度. 以便分拆
int start = temp.ToLower().IndexOf(@"<");
int end = temp.ToLower().IndexOf(@">") + 1;
string strTableStyle = temp.Substring(start,end-start);
//因为要将DataGrid划分为三个表格, 所以用一个大的DIV固定它们的宽度.并且保证scroll bar不出现.
//要确保scroll bar不出, 用overflow-y:hidden就够了
if (this.Height.ToString() == string.Empty || this.Height.ToString() == "100%")
{
sbRenderedTable.Insert(0,@"<div id='" + this.ID + "_full' style='Align:center; WIDTH: 100%; overflow-y:hidden'>");
}
else
{
sbRenderedTable.Insert(0,@"<div id='" + this.ID + "_full' style='Align:center; Width: 100%; overflow-y:hidden;Height:" + this.Height.ToString() + @"'>");
}
temp = sbRenderedTable.ToString();
strTableStyle = strTableStyle.Replace(this.ID+"_Headers", ID + "_Items");
//将表头与内容分拆开. 并为内容加入一个DIV以显示scroll bar
sbRenderedTable.Insert((temp.ToLower()).IndexOf(@"</tr>") + 5,@"</table>"+ @"<div id='" + this.ID + @"_div' style= 'WIDTH:100%;TOP:;LEFT:;POSITION:;Z-INDEX:;OVERFLOW-X: hidden;OVERFLOW-Y:auto'>
" + strTableStyle);
string strTablePager = strTableStyle.Replace(this.ID + "_Items", this.ID + "_Pager");
int intHeightIndex = strTablePager.ToLower().IndexOf("height:");
if (intHeightIndex > 0)
{
strTablePager = strTablePager.Remove(intHeightIndex, this.Height.ToString().Length+8);
}
//将内容与分页拆开.
sbRenderedTable.Insert(sbRenderedTable.ToString().ToLower().IndexOf(@"<tr style"),@"</table></div>"+strTablePager);
//使用Javascript将表头的列与内容的列的宽度匹配.
StringBuilder adjustStyleScript = new StringBuilder();
adjustStyleScript.Append(@"<script language=javascript>");
adjustStyleScript.Append(@"var headerTableRow = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.rows[0];");
// 判断记录是否为0, 如果为0则无需匹配表头与内容的列宽
adjustStyleScript.Append(@" if (");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length !=0) {");
adjustStyleScript.Append(@"var originalTableRow = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[0];");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.rows[0].width = originalTableRow.offsetWidth;");
adjustStyleScript.Append(this.ID + @"_Headers.style.width = " + this.ID + @"_full.offsetWidth;");
adjustStyleScript.Append(this.ID + @"_Pager.style.width = " + this.ID + @"_full.offsetWidth;");
adjustStyleScript.Append(@"for (var i = 0; i < headerTableRow.cells.length; i++) {");
adjustStyleScript.Append(@"headerTableRow.cells[i].width = originalTableRow.cells[i].offsetWidth;}");
adjustStyleScript.Append(@"}");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.style.left = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.offsetLeft;");
adjustStyleScript.Append(@"var MinItemHeight = 100;");
//统计每页一共有多少条记录
adjustStyleScript.Append(@"var itemsRowsLength = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length;");
//计算Items表生成的实际高度.
adjustStyleScript.Append(@"var itemsTotalHeight = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[0].offsetHeight * itemsRowsLength;");
// 判断整个控件的高度是否比预设的高度要小.
adjustStyleScript.Append(@"if (");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetHeight < MinItemHeight) {");
// 判断实际高度是否比减去表头和表脚的高度要小.
adjustStyleScript.Append(@"if (itemsTotalHeight < MinItemHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight) {");
// 将Items外面的Div高度设定与实际生成高度相同.
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.Height = itemsTotalHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetWidth;");
// 每行的高度等于实际高度的平均值
adjustStyleScript.Append(@"for (var i = 0; i<");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length; i++) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[i].height = itemsTotalHeight / itemsRowsLength; }");
adjustStyleScript.Append(@" }else{");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.height = MinItemHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.offsetWidth + 17+ 'px';");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.style.height = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight + MinItemHeight + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
adjustStyleScript.Append(@"}");
adjustStyleScript.Append(@"} else {");
// 当整个控件的高度比预设大, 计算去除表头和表脚后的高度.
adjustStyleScript.Append(@"var itemsHeight = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
// 判断Items表格的高度是否比去除表头和表脚后的高度要小.
adjustStyleScript.Append(@"if (itemsTotalHeight < itemsHeight) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetWidth;");
adjustStyleScript.Append(@"for (var i = 0; i<");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length; i++) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[i].height = itemsTotalHeight / itemsRowsLength;");
adjustStyleScript.Append(@" }");
adjustStyleScript.Append(@" } else {");
// 判断是否需要滚动条
adjustStyleScript.Append(@"if (");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.offsetHeight > itemsHeight) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.offsetWidth + 17+ 'px';");
adjustStyleScript.Append(@"} else {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.style.height = itemsHeight;");
adjustStyleScript.Append(@" }");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.height = itemsHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetWidth;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.style.height = itemsHeight + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
adjustStyleScript.Append(@" } } ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.top = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetTop + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.style.top = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.offsetTop;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.style.position = 'static';");
adjustStyleScript.Append(@"</script>");
Page.RegisterStartupScript("dummyKey" + this.ID, adjustStyleScript.ToString());
sbRenderedTable.Append(@"</div>");
writer.Write(sbRenderedTable.ToString());
}
else
{
sbRenderedTable.Replace(ID,ID + "_Headers", 0, (temp.IndexOf(ID) + ID.Length));
//将高度去掉.
sbRenderedTable.Remove(sbRenderedTable.ToString().ToLower().IndexOf("height:"), this.Height.ToString().Length+8);
// 因为表头存在两行. 所以要分别截取,以统计两行的字符串数.
int intHeaderLength = 0;
StringBuilder sbNewTable = new StringBuilder(sbRenderedTable.ToString());
string strBackup;
string strTableStyle;
temp = sbRenderedTable.ToString();
int start = temp.ToLower().IndexOf(@"<");
int end = temp.ToLower().IndexOf(@">") + 1;
// 将表头格式保存到strBackup和strTableStyle中
// strBackup的作用是用于统计, <table>, 第一行, 第二行表头的字符串长度.
// strTableStyle的作用是保存<table>的样式.
strBackup = strTableStyle = temp.Substring(start,end-start);
intHeaderLength += strBackup.Length;
sbNewTable.Remove(start,end-start);
temp = sbNewTable.ToString();
start = temp.ToLower().IndexOf(@"<tr");
end = temp.ToLower().IndexOf(@"</tr>") + 5;
strBackup = temp.Substring(start,end-start);
intHeaderLength += strBackup.Length;
sbNewTable.Remove(start,end-start);
temp = sbNewTable.ToString();
start = temp.ToLower().IndexOf(@"<tr");
end = temp.ToLower().IndexOf(@"</tr>") + 5;
strBackup = temp.Substring(start,end-start);
intHeaderLength += strBackup.Length;
strTableStyle = strTableStyle.Replace(this.ID+"_Headers", ID + "_Items");
sbRenderedTable.Insert(intHeaderLength+3,@"</table>"+ @"<div id='" + this.ID + @"_div' style= 'WIDTH:100%;TOP:;LEFT:;POSITION:;Z-INDEX:;OVERFLOW-X: hidden;OVERFLOW-Y:auto'>
" + strTableStyle);
//因为要将DataGrid划分为三个表格, 所以用一个大的DIV固定它们的宽度.并且保证scroll bar不出现.
//要确保scroll bar不出, 用overflow-y:hidden就够了
if (this.Height.ToString() == string.Empty || this.Height.ToString() == "100%")
{
sbRenderedTable.Insert(0,@"<div id='" + this.ID + "_full' style='Align:center; WIDTH: 100%; overflow-y:hidden'>");
}
else
{
sbRenderedTable.Insert(0,@"<div id='" + this.ID + "_full' style='Align:center; Width: 100%; overflow-y:hidden;Height:" + this.Height.ToString() + @"'>");
}
string strTablePager = strTableStyle.Replace(this.ID+"_Items", this.ID+"_Pager");
sbRenderedTable.Insert(sbRenderedTable.ToString().ToLower().IndexOf(@"<tr style"),@"</table></div>"+strTablePager);
StringBuilder adjustStyleScript = new StringBuilder();
adjustStyleScript.Append(@"<script language=javascript>");
adjustStyleScript.Append(@"var headerTableRow = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.rows[1];");
adjustStyleScript.Append(@" if (");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length !=0) {");
adjustStyleScript.Append(@"var originalTableRow = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[0];");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.rows[0].width = originalTableRow.offsetWidth;");
adjustStyleScript.Append(this.ID + @"_Headers.style.width = " + this.ID + @"_full.offsetWidth;");
adjustStyleScript.Append(this.ID + @"_Pager.style.width = " + this.ID + @"_full.offsetWidth;");
adjustStyleScript.Append(@"for (var i = 0; i < headerTableRow.cells.length; i++) {");
adjustStyleScript.Append(@"headerTableRow.cells[i].width = originalTableRow.cells[i].offsetWidth;}");
adjustStyleScript.Append(@"}");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.style.left = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.offsetLeft;");
adjustStyleScript.Append(@"var MinItemHeight = 120;");
//统计每页一共有多少条记录
adjustStyleScript.Append(@"var itemsRowsLength = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length;");
//计算Items表生成的实际高度.
adjustStyleScript.Append(@"var itemsTotalHeight = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[0].offsetHeight * itemsRowsLength;");
// 判断整个控件的高度是否比预设的高度要小.
adjustStyleScript.Append(@"if (");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetHeight < MinItemHeight) {");
// 判断实际高度是否比减去表头和表脚的高度要小.
adjustStyleScript.Append(@"if (itemsTotalHeight < MinItemHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight) {");
// 将Items外面的Div高度设定与实际生成高度相同.
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.Height = itemsTotalHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetWidth;");
// 每行的高度等于实际高度的平均值
adjustStyleScript.Append(@"for (var i = 0; i<");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length; i++) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[i].height = itemsTotalHeight / itemsRowsLength; }");
adjustStyleScript.Append(@" }else{");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.height = MinItemHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.offsetWidth + 17+ 'px';");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.style.height = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight + MinItemHeight + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
adjustStyleScript.Append(@"}");
adjustStyleScript.Append(@"} else {");
// 当整个控件的高度比预设大, 计算去除表头和表脚后的高度.
adjustStyleScript.Append(@"var itemsHeight = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight - ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
// 判断Items表格的高度是否比去除表头和表脚后的高度要小.
adjustStyleScript.Append(@"if (itemsTotalHeight < itemsHeight) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetWidth;");
adjustStyleScript.Append(@"for (var i = 0; i<");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows.length; i++) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.rows[i].height = itemsTotalHeight / itemsRowsLength;");
adjustStyleScript.Append(@" }");
adjustStyleScript.Append(@" } else {");
// 判断是否需要滚动条
adjustStyleScript.Append(@"if (");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.offsetHeight > itemsHeight) {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.offsetWidth + 17+ 'px';");
adjustStyleScript.Append(@"} else {");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.style.height = itemsHeight;");
adjustStyleScript.Append(@" }");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.height = itemsHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.style.width = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.offsetWidth;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_full.style.height = itemsHeight + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Pager.offsetHeight;");
adjustStyleScript.Append(@" } } ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.top = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetTop + ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.offsetHeight;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Items.style.top = ");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_div.offsetTop;");
adjustStyleScript.Append(this.ID);
adjustStyleScript.Append(@"_Headers.style.position = 'static';");
adjustStyleScript.Append(@"</script>");
Page.RegisterStartupScript("dummyKey" + this.ID, adjustStyleScript.ToString());
sbRenderedTable.Append(@"</div>");
writer.Write(sbRenderedTable.ToString());
}
}
}
else
{
// 不会执行此句, 只有在设计视图中出现DataGrid
base.Render(writer);
}
}