单元格合并原理其实很简单,就是逐行判断要合并的单元格里的值是否和上一行的相同,要是相同的话就合并,不同的话就接着判断

我们可以通过扩展方法为GridView添加单元合并

 

我为GridView 创建了个RowSpan的方法 .   有一个object 参数 

为什要定义object 参数  源于ASP.NET MVC 的Routing 组件配置规则  感觉这种方式很不错..

所以使用了这种方式来进行.

 

 

1 

public

static

class
GridViewExtensions
2
{
3

///

<summary>

4

///
GridView行合并
5

///

</summary>

6

///

<param name="gridView"></param>

7

///

<param name="field">
合并参数(匿名类型)
8

///
ColumnIndex:要合并行的索引 (以0开始,必须指定)
9

///
ColumnControlID(可选):如果该行为模板行则必须指定
10

///
PropertyName:根据ID属性 默认值为Text
11

///
Colums:(string类型)表示额外的行合并方式和ColumnIndex一样(多个使用逗号隔开,如Colums="5,6,7,8")
12

///
例:
13

///
合并第一行(第一行为模板行),绑定的一个Label名称为lblName 根据Text属性值合并 第6行方式和第一行相同
14

///
new {ColumnIndex=0,ColumnControlID="lblName",PropertyName="Text",Columns="5"}
15

///

</param>

16


public

static
GridView RowSpan(
this
GridView gridView,
object
field)
17
{
18
Dictionary
<
string
,
string
>
rowDictionary
=
ObjectLoadDictionary(field);
19

int
columnIndex
=

int
.Parse(rowDictionary[
"
ColumnIndex
"
]);
20

string
columnName
=
rowDictionary[
"
ColumnControlID
"
];
21

string
propertyName
=
rowDictionary[
"
PropertyName
"
];
22

string
columns
=
rowDictionary[
"
Columns
"
];
23

for
(var i
=

0
; i
<
gridView.Rows.Count; i
++
)
24
{
25

26

int
rowSpanCount
=

1
;
27

for
(
int
j
=
i
+

1
; j
<
gridView.Rows.Count; j
++
)
28
{
29

//
绑定行合并处理

30


if
(
string
.IsNullOrEmpty(columnName))
31
{
32

//
比较2行的值是否相同

33


if
(gridView.Rows[i].Cells[columnIndex].Text
==
gridView.Rows[j].Cells[columnIndex].Text)
34
{
35

//
合并行的数量+1

36

rowSpanCount
++
;
37

//
隐藏相同的行

38

gridView.Rows[j].Cells[columnIndex].Visible
=

false
;
39

if
(
!
string
.IsNullOrEmpty(columns))
40
{
41
columns.Split(
'
,
'
).ToList
<
string
>
().ForEach(c
=>
gridView.Rows[j].Cells[
int
.Parse(c)].Visible
=
false
);
42
}
43
}
44

else

45
{
46

break
;
47
}
48
}
49

else

50
{
51

//
模板行的合并处理

52


if
(GetPropertyValue(gridView.Rows[i].Cells[columnIndex].FindControl(columnName), propertyName).ToString()
==
GetPropertyValue(gridView.Rows[j].Cells[columnIndex].FindControl(columnName), propertyName).ToString())
53
{
54
rowSpanCount
++
;
55

//
隐藏相同的行

56

gridView.Rows[j].Cells[columnIndex].Visible
=

false
;
57

if
(
!
string
.IsNullOrEmpty(columns))
58
{
59

60
columns.Split(
'
,
'
).ToList
<
string
>
().ForEach(c
=>
gridView.Rows[j].Cells[
int
.Parse(c)].Visible
=

false
);
61
}
62
}
63

else

64
{
65

break
;
66
}
67
}
68
}
69

if
(rowSpanCount
>

1
)
70
{
71

//
行合并

72

gridView.Rows[i].Cells[columnIndex].RowSpan
=
rowSpanCount;
73

//
判断是否有额外的行需要合并

74


if
(
!
string
.IsNullOrEmpty(columns))
75
{
76

//
额外的行合并

77

columns.Split(
'
,
'
).ToList
<
string
>
().ForEach(c
=>
gridView.Rows[i].Cells[
int
.Parse(c)].RowSpan
=
rowSpanCount);
78
}
79
i
=
i
+
rowSpanCount
-

1
;
80
}
81

82

83
}
84

return
gridView;
85
}
86

87

private

static
Dictionary
<
string
,
string
>
ObjectLoadDictionary(
object
fields)
88
{
89
Dictionary
<
string
,
string
>
resultDictionary
=

new
Dictionary
<
string
,
string
>
();
90
PropertyInfo[] property
=
fields.GetType().GetProperties(BindingFlags.Instance
|
BindingFlags.DeclaredOnly
|
BindingFlags.Public
|
BindingFlags.GetProperty);
91

foreach
(PropertyInfo tempProperty
in
property)
92
{
93
resultDictionary.Add(tempProperty.Name, tempProperty.GetValue(fields,
null
).ToString());
94
}
95

//
指定默认值

96


if
(
!
resultDictionary.Keys.Contains(
"
ColumnIndex
"
))
97
{
98

throw

new
Exception(
"
未指定要合并行的索引 ColumnIndex 属性!
"
);
99
}
100

if
(
!
resultDictionary.Keys.Contains(
"
ColumnControlID
"
))
101
{
102
resultDictionary.Add(
"
ColumnControlID
"
,
null
);
103
}
104

105

if
(
!
resultDictionary.Keys.Contains(
"
PropertyName
"
))
106
{
107
resultDictionary.Add(
"
PropertyName
"
,
"
Text
"
);
108
}
109

110

if
(
!
resultDictionary.Keys.Contains(
"
Columns
"
))
111
{
112
resultDictionary.Add(
"
Columns
"
,
null
);
113
}
114

115

116

117

118

return
resultDictionary;
119
}
120

121

///

<summary>

122

///
获取一个对象的一个属性..
123

///

</summary>

124

///

<param name="obj"></param>

125

///

<param name="PropertyName">
属性名称
</param>

126

///

<returns>
属性的值, 如果无法获取则返回null
</returns>

127


private

static

object
GetPropertyValue(
object
obj,
string
PropertyName)
128
{
129
PropertyInfo property
=
obj.GetType().GetProperty(PropertyName);
130

return
property.GetValue(obj,
null
);
131
}
132
}


这个扩展方法的使用方式很简单

 


 var s  =   new [] { 

                

new  { 姓名  =   " 张三 " , 性别  =   " 男 " , 语文  =  86f, 数学  =  90f, 学期  =   " 第一学期 "  },  

                

new  { 姓名  =   " 张三 " , 性别  =   " 男 " , 语文  =  89f, 数学  =  98f, 学期  =   " 第二学期 "  }, 

                

new  { 姓名  =   " 李四 " , 性别  =   " 男 " , 语文  =  89f, 数学  =  64f, 学期  =   " 第一学期 "  },  

                

new  { 姓名  =   " 李四 " , 性别  =   " 男 " , 语文  =  75f, 数学  =  64f, 学期  =   " 第二学期 "  },

                

new  { 姓名  =   " 王五 " , 性别  =   " 男 " , 语文  =  89f, 数学  =  64f, 学期  =   " 第一学期 "  },  

                

new  { 姓名  =   " 王五 " , 性别  =   " 男 " , 语文  =  63f, 数学  =  93f, 学期  =   " 第二学期 "  }

            };

            

this .GridView1.DataSource  =  s;

            

this .GridView1.DataBind();

            

this .GridView1.RowSpan( new  { ColumnIndex  =   0 , Columns  =   " 1 "  }); 


我们合并第1列的值姓名..  GirdView索引是从0开始的所以ColumnIndex=0 性别肯定和姓名对应的

可以是用Colunmns="" 这个属性来指定哪个列的合并方式和 ColumnIndex指定的列相同  多个用 ","隔开比如 Colunmns="2,3,4,5"这种方式

如果GridView中使用了模板列 则除了需要指定ColumnIndex外还需要添加ID和PropertyName属性

如 new {ColumnIndex=0,ID="lblName",PropertyName="Text",Columns="1" }

 

注:暂时只能指定普通属性如Text 或Value ;SelectedItem.Value 这种属性需要修改部分代码  也不能包含容器控件 修改部分代码可以支持容器控件

效果图

姓名

性别

语文

数学

学期

张三


86

90

第一学期

89

98

第二学期

李四


89

64

第一学期

75

64

第二学期

王五


89

64

第一学期

63

93

第二学期

 

合并姓名和语文相同的分数

 


   var s  =   new [] { 

                

new  { 姓名  =   " 张三 " , 性别  =   " 男 " , 语文  =  86f, 数学  =  90f, 学期  =   " 第一学期 "  },  

                

new  { 姓名  =   " 张三 " , 性别  =   " 男 " , 语文  =  89f, 数学  =  98f, 学期  =   " 第二学期 "  }, 

                

new  { 姓名  =   " 李四 " , 性别  =   " 男 " , 语文  =  89f, 数学  =  64f, 学期  =   " 第一学期 "  },  

                

new  { 姓名  =   " 李四 " , 性别  =   " 男 " , 语文  =  75f, 数学  =  64f, 学期  =   " 第二学期 "  },

                

new  { 姓名  =   " 王五 " , 性别  =   " 男 " , 语文  =  89f, 数学  =  64f, 学期  =   " 第一学期 "  },  

                

new  { 姓名  =   " 王五 " , 性别  =   " 男 " , 语文  =  63f, 数学  =  93f, 学期  =   " 第二学期 "  }

            };

            

this .GridView1.DataSource  =  s;

            

this .GridView1.DataBind();

            

this .GridView1.RowSpan( new  { ColumnIndex  =   0 , Columns  =   " 1 "  });

            

this .GridView1.RowSpan( new  { ColumnIndex  =   2  });


 

姓名

性别

语文

数学

学期

张三


86

90

第一学期

89

98

第二学期

李四


64

第一学期

75

64

第二学期

王五


89

64

第一学期

63

93

第二学期

可以使用这种方式


this
.GridView1.RowSpan(
new
{ ColumnIndex
=

0
, Columns
=

"
1
"
}).RowSpan(
new
{ ColumnIndex
=

2
}).RowSpan(
new
{ ColumnIndex
=

3
});


 

姓名

性别

语文

数学

学期

张三


86

90

第一学期

89

98

第二学期

李四


64

第一学期

75

第二学期

王五


89

第一学期

63

93

第二学期