最近,去了新公司,由于限制了网络,有过一阵子没有写东西了,只能周末在家的时候有时间写。本想写一些最近关于学习CRM2011的学习心得,但一方面考虑到公司限网,另一方面,网上已经有大神写了非常详细的一个CRM2011编程系列,因此就打消了这个念头,只好记录下一些工作中常用到的技术点,就当备忘吧,也供大家参考。
要实现的效果如下:
(图1)
(图2)
实现思路:大家都知道,Gridview控件,生成的html代码其实就是对应的一个table。要合并某一列中数据相同的行,会用到该单元格也即td的RowSpan属性。1、当Gridview中有数据时,我先取第一行中要合并列的文本,并设置第一行中指定的列不跨行,记录下待合并列的索引位置。2、遍历Gridview中的数据,但是要从第二行开始遍历。如果有文本和前一行中指定的列文本相同,则先隐藏这一单元格中的文本,再设置上一单元格的RowSpan+1(有多少连续相同值的行,就跨多少行)。如果不同,则重新更新 要合并的文本和待合并单元格起始索引,RowSpan默认为1。3、合并单元格方法应放置在DataBind事件中。
(图1)代码如下:
/// <summary>
/// 合并行(普通列)
/// </summary>
/// <param name="gv">Girdview对象</param>
/// <param name="columnIndex">要合并的列的索引</param>
public static void UnitCell(GridView gv, int columnIndex)
{
int i;
string lastText; //合并行中列的文本
int lastCell; //待合并单元格的起始索引
if (gv.Rows.Count > 0)
{
lastType = gv.Rows[0].Cells[columnIndex].Text;
gv.Rows[0].Cells[columnIndex].RowSpan = 1;
lastCell = 0;
for (i = 1; i < gv.Rows.Count; i++)
{
if (gv.Rows[i].Cells[columnIndex].Text == lastText) //连续行的文本相同
{
gv.Rows[i].Cells[columnIndex].Visible = false;
gv.Rows[lastCell].Cells[columnIndex].RowSpan++;
}
else
{
lastType = gv.Rows[i].Cells[columnIndex].Text;
lastCell = i;
gv.Rows[i].Cells[columnIndex].RowSpan = 1;
}
}
}
}
/// <summary>
/// 合并行(模板列)
/// </summary>
/// <param name="gv">Girdview对象</param>
/// <param name="columnIndex">要合并的列的索引</param>
/// <param name="lblName">模板列里面label的ID</param>
public static void UnitCell(GridView gv, int columnIndex, string lblName)
{
int i;
string lastType; //合并行中列的文本
int lastCell; //待合并单元格的起始索引
if (gv.Rows.Count > 0)
{
lastType = (gv.Rows[0].Cells[columnIndex].FindControl(lblName) as Label).Text;
gv.Rows[0].Cells[columnIndex].RowSpan = 1;
lastCell = 0;
for (i = 1; i < gv.Rows.Count; i++)
{
if ((gv.Rows[i].Cells[columnIndex].FindControl(lblName) as Label).Text == lastText) //连续行的文本相同
{
gv.Rows[i].Cells[columnIndex].Visible = false;
gv.Rows[lastCell].Cells[columnIndex].RowSpan++;
}
else
{
lastType = (gv.Rows[i].Cells[columnIndex].FindControl(lblName) as Label).Text;
lastCell = i;
gv.Rows[i].Cells[columnIndex].RowSpan = 1;
}
}
}
}
public string GetGenderName(object obj)
{
return Convert.ToBoolean(obj) == true ? "男" : "女";
}
//为什么写在这里?这里是gridview数据绑定完之后,执行的方法。考虑到分页后,或者页面刷新等原因
protected void GridView1_DataBound(object sender, EventArgs e)
{
UnitCell(GridView1, 9, "lbl");
}
(图2)cs代码如下:
protected void gdvWaterFee_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onmouseover", "if(this!=prevselitem){this.style.backgroundColor='#Efefef'}");//当鼠标停留时更改背景色
e.Row.Attributes.Add("onmouseout", "if(this!=prevselitem){this.style.backgroundColor='#ffffff'}");//当鼠标移开时还原背景色
e.Row.Attributes.Add("onclick", e.Row.ClientID.ToString() + ".checked=true;selectx(this,11,8)"); //单击时改变行中指定列的背景色
}
}
protected void gdvWaterFee_DataBound(object sender, EventArgs e)
{
int index = 3;
int endIndex = 9;
for (int i = index; i <= endIndex; i++)
{
UnitCell(gdvWaterFee, i, index);
}
}
/// <summary>
/// 合并行(普通列)
/// </summary>
/// <param name="gv">Girdview对象</param>
/// <param name="columnIndex">要合并的列的索引</param>
/// <param name="textIndex">比较文本相同的列索引(如果此列的文本相同则合并指定列)</param>
public static void UnitCell(GridView gv,int columnIndex, int textIndex)
{
int i;
string lastText; //合并行中列的文本
int lastCell; //待合并单元格的起始索引
if (gv.Rows.Count > 0)
{
lastText = gv.Rows[0].Cells[textIndex].Text;
gv.Rows[0].Cells[columnIndex].RowSpan = 1;
lastCell = 0;
for (i = 1; i < gv.Rows.Count; i++)
{
if (gv.Rows[i].Cells[textIndex].Text == lastText) //连续行的文本相同
{
gv.Rows[i].Cells[columnIndex].Visible = false;
gv.Rows[lastCell].Cells[columnIndex].RowSpan++;
}
else
{
lastText = gv.Rows[i].Cells[textIndex].Text;
lastCell = i;
gv.Rows[i].Cells[columnIndex].RowSpan = 1;
}
}
}
}
js代码如下:
var bgColor = '#A7CDF0'; //蓝色
var bgColor1 = '#ffffff'; //白色
var prevselitem = null;
//选中行变色 参数示例:11,8 (row:点击变色的行对象,cCounts:总共的列数,cIndex:此列索引后面的列都变色)
function selectx(row,cCounts,cIndex) {
if (prevselitem != null) {
for (var v = 0; v <= cCounts; v++) {
if (prevselitem.cells.length == 5) {
if (v < 5) {
prevselitem.cells[v].style.backgroundColor = bgColor1;
}
}
else {
prevselitem.cells[v].style.backgroundColor = bgColor1;
}
}
}
for (var v = 0; v <= cCounts; v++) {
if (row.cells.length == 5) {
if (v < 5) {
row.cells[v].style.backgroundColor = bgColor;
}
}
else {
if (v < 2 || v > cIndex) {
row.cells[v].style.backgroundColor = bgColor;
}
}
}
prevselitem = row;
}
总结:鼠标移到行上时设置该行的背景颜色,鼠标移开时,还原背景颜色。鼠标单击该行时,给该行设置颜色,并把该行存起来,当再次点击行时,先将存起来的那一行颜色复原,再给新点击的行设置颜色。如果要设置行中指定单元格的背景颜色,则只要以单元格为单位设置其背景颜色即可。
关于全选和反选功能,太简单,我这里只提一下思路。单击全选按钮时,判断该按钮是否为选中,如果为选中,则遍历该Gridview中所有的checkbox,并设置其为选中,否则设置为不选中。当单击Gridview数据行中的复选框时,再次遍历Gridview中所有复选框,如果选中的数量等于总数,则全选框选中,否则不选中。关键代码如下:
//获Ggridview中所有的复选框 sName: Gridview 的ID
function getCheckbox(sName) {
var aryCheckbox = new Array();
var tb = document.getElementById(sName);
if (tb == null)
return;
var objs = tb.getElementsByTagName("input");
for (var i = 0; i < objs.length; i++) {
if (objs[i].type == 'checkbox' && startsWith(objs[i].id, sName))
aryCheckbox.push(objs[i]);
}
return aryCheckbox;
}
//监听每一行的复选框,控制全选、反选按钮
function controlSelectAll(t) {
var tblName, cbkAll; //Gridview ID ,全选框ID
if (t == 1) { //水费
tblName = "gdvWaterFee";
cbkAll = "chkAllFee";
}
else if(t==2) //代收费
{
var tblName = "gdvCollFee";
var cbkAll = "chkAllColl";
}
else
{
return;
}
var chks = getCheckbox(tblName);
var count = 0;
for (var i = 0; i < chks.length; i++) {
if (chks[i].checked == true) {
count++;
}
}
if (count < chks.length) {
document.getElementById(cbkAll).checked = false;
}
else {
document.getElementById(cbkAll).checked = true;
}
}