(一). 概述
1. 实现GridView表头固定表体滚动效果
2. 继承GridView的所有功能, 增加扩展功能, 表体滚动功能; 不需要另外加辅助滚动控件, 如<DIV>.
3. 支持多行表头滚动, 此控件能够自动检测到使用者增加的表头的行数. 准确的实现表头滚动.
有增加GridView多表头实现方案, 请看[多表头自定义控件].
实现原理:
一般要实现GridView表头固定,表体滚动功能时,都是自己增加一个<DIV>控件,
然后将GridView嵌套在这个<DIV>控件里面;使用这个GridView控件就不用在页面中自己
增加个<DIV>控件了,因为它自动完成了增加<DIV>控件的功能,具有通用性.
(二). 运行如图
1. 单行表头增加自动滚动效果
2. 多行表头增加自动滚动效果
(三). 用法
1. 将GridViewExpendHeader控件Dll添加引用到Web站点工程中
2. 从工具箱拖动一个GridViewExpendHeader控件到设计器中
3. 设置GridViewExpendHeader控件的属性.
a. 设置属性窗口中新增的 "扩展" 类别中的两个属性, 这两个属性是指滚动区域的大小, 如下图所示:
b. 设置GridView本身的高度Height, 这个高度是指滚动区域内的GridView的实际高度, 这个高度数值设置
要大于ScrollHeight滚动条才能够呈现. 简单地说, 本自定义控件自动会实现一个GridView(自己)
的父控件<DIV>, 然后再把自己放在里面, 如果自己高度小于<DIV>高度了, 不用滚动就能够显示
全自己的数据, 滚动条就没有呈现的意义了. 这里讲得有点啰嗦. .
4. F5运行即可
(四). 完整代码
1. 主控件GridViewFixedMultiHeader类代码
1
///
<
summary
>
2
///
Author: [ ChengKing(ZhengJian) ]
3
///
Blog: Http:
//
blog.csdn.net
/
ChengKing
4
///
Date
:
2007
/
4
/
3
5
///
</
summary
>
6
///
<
summary
>
7
///
主控件类, 继承GridView的所有功能
8
///
</
summary
>
9
[ToolboxData(
"
<{0}:GridViewExpendHeader runat=server></{0}:GridViewExpendHeader>
"
)]
10
public
class
GridViewFixedMultiHeader : GridView
11
{
12
[Description(
"
当需要重新构造Header时触发此事件
"
)]
13
public
event
System.EventHandler RebuildHeader;
14
15
private
System.Web.UI.WebControls.Panel pnlScroll
=
new
System.Web.UI.WebControls.Panel();
16
17
#region
扩展
18
///
<
summary
>
19
///
设定滚动容器的宽度
20
///
</
summary
>
21
[Bindable(
true
)]
22
[Category(
"
扩展
"
)]
23
[DefaultValue(
"
500px
"
)]
24
[Localizable(
true
)]
25
[TypeConverter(
typeof
(UnitConverter))]
26
public
Unit ScrollWidth
27
{
28
get
29
{
30
return
pnlScroll.Width;
31
}
32
set
33
{
34
pnlScroll.Width
=
value;
35
}
36
}
37
38
///
<
summary
>
39
///
设定滚动容器的高度
40
///
</
summary
>
41
[Bindable(
true
)]
42
[Category(
"
扩展
"
)]
43
[DefaultValue(
"
150px
"
)]
44
[Localizable(
true
)]
45
[TypeConverter(
typeof
(UnitConverter))]
46
public
Unit ScrollHeight
47
{
48
get
49
{
50
return
pnlScroll.Height;
51
}
52
set
53
{
54
pnlScroll.Height
=
value;
55
}
56
}
57
#endregion
58
59
protected
override void OnPreRender(EventArgs e)
60
{
61
62
StringBuilder sb
=
new
StringBuilder();
63
sb.Append(
"
function Tidy()
"
);
64
sb.Append(
"
{
"
);
65
sb.Append(
"
var gve = document.getElementById(\""+ this.UniqueID +
"
\
"
);
"
);
66
sb.Append(
"
if( gve.rows.length > 0 )
"
);
67
sb.Append(
"
{
"
);
68
sb.Append(
"
var a1 = document.getElementById(\
"
divHeaderContainer
\
"
);
"
);
69
sb.Append(
"
var table1 = document.createElement(\
"
table
\
"
);
"
);
70
sb.Append(
"
var tbody1 = document.createElement(\
"
tbody
\
"
);
"
);
71
sb.Append(
"
table1.style.cssText = \
"
table
-
layout:fixed;border
-
style: solid ;border
-
color:gray; border
-
width: 1px thin;
\
"
;
"
);
72
//
sb.Append(
"
table1.style.cssText = \
"
table
-
layout:fixed;color:#CCCCFF;background
-
color:#
003399
;font
-
weight:bold;
\
"
;
"
);
73
sb.Append(
"
var i;
"
);
74
sb.Append(
"
var blnIfFind = false;
"
);
75
sb.Append(
"
for( i = gve.rows.length - 1; i >= 0; i-- )
"
);
76
sb.Append(
"
{
"
);
77
sb.Append(
"
if( gve.rows[i].children(0).tagName.toUpperCase() != \
"
TH
\
"
&& blnIfFind == false )
"
);
78
sb.Append(
"
{
"
);
79
sb.Append(
"
continue;
"
);
80
sb.Append(
"
}
"
);
81
sb.Append(
"
if( blnIfFind == false )
"
);
82
sb.Append(
"
{
"
);
83
sb.Append(
"
blnIfFind = true;
"
);
84
sb.Append(
"
}
"
);
85
sb.Append(
"
if( tbody1.children.length == 0 )
"
);
86
sb.Append(
"
{
"
);
87
sb.Append(
"
var newRow = gve.rows[i].cloneNode(true);
"
);
88
//
sb.Append(
"
newRow.style.cssText = 'border-style: solid ;border-color:gray; border-width: 1px thin';
"
);
89
sb.Append(
"
tbody1.appendChild( newRow );
"
);
90
sb.Append(
"
}
"
);
91
sb.Append(
"
else
"
);
92
sb.Append(
"
{
"
);
93
sb.Append(
"
var newRow = gve.rows[i].cloneNode(true);
"
);
94
//
sb.Append(
"
newRow.style.cssText = 'border-style: solid ;border-color:gray; border-width: 1px thin';
"
);
95
sb.Append(
"
tbody1.insertBefore( newRow , tbody1.firstChild );
"
);
96
sb.Append(
"
}
"
);
97
sb.Append(
"
}
"
);
98
sb.Append(
"
table1.appendChild(tbody1);
"
);
99
sb.Append(
"
a1.appendChild(table1);
"
);
100
sb.Append(
"
for( i = 0; i < gve.rows.length -1; i++)
"
);
101
sb.Append(
"
{
"
);
102
sb.Append(
"
if( gve.rows[0].children(0).tagName.toUpperCase() != \
"
TH
\
"
)
"
);
103
sb.Append(
"
{
"
);
104
sb.Append(
"
gve.deleteRow(0);
"
);
105
sb.Append(
"
continue;
"
);
106
sb.Append(
"
}
"
);
107
sb.Append(
"
gve.deleteRow(0);
"
);
108
sb.Append(
"
break;
"
);
109
sb.Append(
"
}
"
);
110
sb.Append(
"
}
"
);
111
sb.Append(
"
}
"
);
112
113
if
(!Page.ClientScript.IsClientScriptBlockRegistered(
"
Tidy
"
))
114
{
115
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"
Tidy
"
, sb.ToString(),
true
);
116
}
117
118
if
(!Page.ClientScript.IsStartupScriptRegistered(
"
Init
"
))
119
{
120
Page.ClientScript.RegisterStartupScript(this.GetType(),
"
Init
"
,
"
<script type=\
"
text
/
javascript
\
"
>window.onload = Tidy;</script>
"
,
false
);
121
}
122
123
base.OnPreRender(e);
124
}
125
126
protected
override void Render(HtmlTextWriter writer)
127
{
128
OnRebuildHeader();
129
base.Render(writer);
130
}
131
protected
override void CreateChildControls()
132
{
133
Control parent
=
this.Parent;
134
135
if
(DesignMode
==
false
)
136
{
137
//
生成头容器
<
DIV
>
138
System.Web.UI.HtmlControls.HtmlGenericControl div
=
new
System.Web.UI.HtmlControls.HtmlGenericControl(
"
DIV
"
);
139
div.ID
=
"
divHeaderContainer
"
;
140
div.Style.Add(
"
width
"
, this.Width.ToString());
141
parent.Controls.Add(div);
142
143
Control gridView
=
this;
144
parent.Controls.Remove(gridView);
145
146
pnlScroll.Style.Add(
"
width
"
, this.Width.ToString());
147
pnlScroll.Style.Add(
"
OVERFLOW-Y
"
,
"
scroll
"
);
148
pnlScroll.Style.Add(
"
OVERFLOW-X
"
,
"
hidden
"
);
149
150
pnlScroll.Controls.Add(this);
151
parent.Controls.Add(pnlScroll);
152
153
ChildControlsCreated
=
true
;
154
}
155
156
base.CreateChildControls();
157
}
158
159
protected
virtual void OnRebuildHeader()
160
{
161
//
重新构造Head
162
if
(RebuildHeader !
=
null)
163
{
164
RebuildHeaderEventArgs args
=
new
RebuildHeaderEventArgs();
165
args.GridViewObject
=
this;
166
args.HeaderRowObject
=
this.HeaderRow;
167
168
RebuildHeader(this, args);
169
}
170
171
}
172
}
2. 文件RebuildHeaderEventArgs.cs 代码
1
///
<summary>
2
///
Author: [ ChengKing(ZhengJian) ]
3
///
Blog: Http://blog.csdn.net/ChengKing
4
///
Date: 2007/4/3
5
///
</summary>
6
///
<summary>
7
///
承载重构Header事件所需的参数[Author:ChengKing(ZhengJian)]
8
///
</summary>
9
public
class
RebuildHeaderEventArgs : EventArgs
10
{
11
private
GridViewFixedMultiHeader _GridViewObject;
12
private
GridViewRow _HeaderRowObject;
13
14
///
<summary>
15
///
存储GrivViewExtend对象本身
16
///
</summary>
17
public
GridViewFixedMultiHeader GridViewObject
18
{
19
get
20
{
21
return
_GridViewObject;
22
}
23
set
24
{
25
_GridViewObject
=
value;
26
}
27
}
28
29
///
<summary>
30
///
存储GrivViewExtend的HeaderRow对象
31
///
</summary>
32
public
GridViewRow HeaderRowObject
33
{
34
get
35
{
36
return
_HeaderRowObject;
37
}
38
set
39
{
40
_HeaderRowObject
=
value;
41
}
42
}
43
}
3. 测试页面文件default.aspx代码, 直接拖动一个控件到设计器就OK了. 不需要设置任何属性.
1 <div>
2 <asp:GridView ID="GridViewFixedMultiHeader1" runat="server" </asp:GridView>
3 </div>
4. 在新增自定义事件中增加表头行代码, 这里增加三行表头HeaderRow.
1
///
<summary>
2
///
具体重写方法, 此方法比较灵活, 可以任意设置您需要创建的格式, 比如更复杂的表格
3
///
另外, 可以直接从第二个参数中取得控件对象引用
4
///
</summary>
5
///
<param name="sender"></param>
6
///
<param name="e"></param>
7
protected
void
GridViewExpend1_RebuildHeader(
object
sender, EventArgs e)
8
{
9
//
取得参数e中包含的对象的引用
10
GridViewFixedMultiHeader currentGVE
=
((RebuildHeaderEventArgs)e).GridViewObject;
//
到操作当前GridView的对象引用
11
GridViewRow currentHeaderRow
=
((RebuildHeaderEventArgs)e).HeaderRowObject;
///
/到操作当前GridView's HeaderRow的对象引用
12
13
14
///
<Add line 1>
15
///
/在当前HeaderRow上面增加一行
16
//
创建一个行并设置与GridViewExtend当前的头类型风格一致
17
GridViewRow willAddHeaderRow
=
new
GridViewRow(
0
,
0
, DataControlRowType.Header, DataControlRowState.Normal);
18
willAddHeaderRow.Font.Bold
=
true
;
19
willAddHeaderRow.BackColor
=
Color.FromName(
"
#003399
"
);
20
willAddHeaderRow.ForeColor
=
Color.FromName(
"
#CCCCFF
"
);
21
TableCell cell
=
new
TableCell();
22
cell.Text
=
"
Number
"
;
23
cell.HorizontalAlign
=
HorizontalAlign.Center;
24
willAddHeaderRow.Cells.Add(cell);
25
cell
=
new
TableCell();
26
cell.Text
=
"
Detail
"
;
27
cell.ColumnSpan
=
2
;
28
cell.HorizontalAlign
=
HorizontalAlign.Center;
29
willAddHeaderRow.Cells.Add(cell);
30
//
添加到GridView
31
currentGVE.Controls[
0
].Controls.AddAt(
0
, willAddHeaderRow);
32
33
34
///
<Add line 2>
35
///
/在当前HeaderRow上面再增加一行
36
//
同样创建一个行并设置与GridViewExtend当前的头类型风格一致
37
willAddHeaderRow
=
new
GridViewRow(
0
,
0
, DataControlRowType.Header, DataControlRowState.Normal);
38
willAddHeaderRow.Font.Bold
=
true
;
39
willAddHeaderRow.BackColor
=
Color.FromName(
"
#003399
"
);
40
willAddHeaderRow.ForeColor
=
Color.FromName(
"
#CCCCFF
"
);
41
42
cell
=
new
TableCell();
43
cell.Text
=
"
Fruits category information
"
;
44
cell.ColumnSpan
=
3
;
45
cell.HorizontalAlign
=
HorizontalAlign.Center;
46
willAddHeaderRow.Cells.Add(cell);
47
//
添加到GridView
48
currentGVE.Controls[
0
].Controls.AddAt(
0
, willAddHeaderRow);
49
50
//
还可以继续增加N个表头行;
51
//
不管增加多么, GridView控件都能够自动检测到HeaderRow的个数, 并且能够正确呈现滚动条
52
//
..;
53
//
..;
54
}
(五). 示例代码下载
http://files.cnblogs.com/MVP33650/extendgridviewfixedmultiheader.rar
(六). 控件开发其它相关文章:
http://blog.csdn.net/ChengKing/category/288694.aspx
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1552251