GridView多行多列合并单元格(完整代码和例子)

GitHub项目地址:https://github.com/mingceng/merge-gridviewcell

使用GridView展示数据,经常会遇到合并单元格的情况。首先说明一下项目中合并单元格的要求,如下图所示,左边是合并之前的GridView,右边是合并之后的GridView。从图中可以看到GridView一共有“等级”、“颜色”,“箱子”,“净重”,“规格”,“汇总”6列,首先要要合并等级,如右图中合并后的“一级”,然后再合并每个等级下面的颜色,如右图中合并后的“一级”下面的“片红”和“条红”,依次类推。


从网上搜索了一下“GridView合并单元格”,大多是合并单列,诸如此类。搜索未果,只能自己动手写一个了。参考现有的合并单列的代码,我完成了满足上面合并要求的代码,自我感觉算法很烂,写这篇文章也是希望有经验的园友提供更好的解决方法。

首先,完成合并单列的行,代码如下:

   1:  /// <summary>
   2:  /// 合并单列的行
   3:  /// </summary>
   4:  /// <param name="gv">GridView</param>
   5:  /// <param name="currentCol">当前列</param>
   6:  /// <param name="startRow">开始合并的行索引</param>
   7:  /// <param name="endRow">结束合并的行索引</param>
   8:  private static void MergeRow(GridView gv, int currentCol, int startRow, int endRow)
   9:  {
  10:      for (int rowIndex = endRow; rowIndex >= startRow; rowIndex--)
  11:      {
  12:          GridViewRow currentRow = gv.Rows[rowIndex];
  13:          GridViewRow prevRow = gv.Rows[rowIndex + 1];
  14:          if (currentRow.Cells[currentCol].Text != "" && currentRow.Cells[currentCol].Text != " ")
  15:          {
  16:              if (currentRow.Cells[currentCol].Text == prevRow.Cells[currentCol].Text)
  17:              {
  18:                  currentRow.Cells[currentCol].RowSpan = prevRow.Cells[currentCol].RowSpan < 1 ? 2 : prevRow.Cells[currentCol].RowSpan + 1;
  19:                  prevRow.Cells[currentCol].Visible = false;
  20:              }
  21:          }
  22:      }
  23:  }

在合并后面的列之前,首先要遍历前一列。上面的例子中,合并第二列,首先要遍历第一列,以便得到一级是从第几行到第几行。开始写遍历前一列的代码之前,首先定义一个类,如下所示:

   1:          class RowArg
   2:          {
   3:              public int StartRowIndex { get; set; }
   4:              public int EndRowIndex { get; set; }
   5:          }

该类有两个属性,分别表示要合并的开始行的索引和结束行的索引。下面是遍历前一列的代码:

   1:  /// <summary>
   2:  /// 遍历前一列
   3:  /// </summary>
   4:  /// <param name="gv">GridView</param>
   5:  /// <param name="prevCol">当前列的前一列</param>
   6:  /// <param name="list"></param>
   7:  private static void TraversesPrevCol(GridView gv, int prevCol, List<RowArg> list)
   8:  {
   9:      if (list == null)
  10:      {
  11:          list = new List<RowArg>();
  12:      }
  13:      RowArg ra = null;
  14:      for (int i = 0; i < gv.Rows.Count; i++)
  15:      {
  16:          if (!gv.Rows[i].Cells[prevCol].Visible)
  17:          {
  18:              continue;
  19:          }
  20:          ra = new RowArg();
  21:          ra.StartRowIndex = gv.Rows[i].RowIndex;
  22:          ra.EndRowIndex = ra.StartRowIndex + gv.Rows[i].Cells[prevCol].RowSpan - 2;
  23:          list.Add(ra);
  24:      }
  25:  }

下面完成最后一个方法,代码如下:

   1:  /// <summary>
   2:  /// GridView合并行,
   3:  /// </summary>
   4:  /// <param name="gv">GridView</param>
   5:  /// <param name="startCol">开始列</param>
   6:  /// <param name="endCol">结束列</param>
   7:  public static void MergeRow(GridView gv, int startCol, int endCol)
   8:  {
   9:      RowArg init = new RowArg()
  10:      {
  11:          StartRowIndex = 0,
  12:          EndRowIndex = gv.Rows.Count - 2
  13:      };
  14:      for (int i = startCol; i < endCol + 1; i++)
  15:      {
  16:          if (i > 0)
  17:          {
  18:              List<RowArg> list = new List<RowArg>();
  19:              //从第二列开始就要遍历前一列
  20:              TraversesPrevCol(gv, i - 1, list);
  21:              foreach (var item in list)
  22:              {
  23:                  MergeRow(gv, i, item.StartRowIndex, item.EndRowIndex);
  24:              }
  25:          }
  26:          //合并开始列的行
  27:          else
  28:          {
  29:              MergeRow(gv, i, init.StartRowIndex, init.EndRowIndex);
  30:          }
  31:      }
  32:  }

这个方法是最后在程序中调用的方法。

最后写个简单的例子:

页面代码:

   1:  <asp:GridView ID="Gridview1" runat="server" AutoGenerateColumns="false" 
   2:      onrowdatabound="Gridview1_RowDataBound">
   3:      <Columns>
   4:          <asp:BoundField DataField="Name" HeaderText="姓名" />
   5:          <asp:BoundField DataField="Item" HeaderText="工资项" />
   6:          <asp:BoundField DataField="SubItem" HeaderText="工资子项" />
   7:          <asp:BoundField DataField="Month" HeaderText="月份" />
   8:          <asp:BoundField DataField="Money" HeaderText="钱数" />
   9:      </Columns>
  10:  </asp:GridView>

后台代码:

   1: public partialclass WebForm1 : System.Web.UI.Page

   2: {

   3:     protectedvoid Page_Load(objectsender, EventArgs e)

   4:     {

   5:         if(!Page.IsPostBack)

   6:         {

   7:             #region 模拟数据

   8:             List<Salary>salaryList = new List<Salary>();

   9:             salaryList.Add(new Salary()

  10:             {

  11:                 Name = "张三",

  12:                 Item = "应发工资",

  13:                 SubItem = "基本工资",

  14:                 Month = "1月",

  15:                 Money = "3000"

  16:             });

  17:             salaryList.Add(new Salary()

  18:             {

  19:                 Name = "张三",

  20:                 Item = "应发工资",

  21:                 SubItem = "奖金",

  22:                 Month = "1月",

  23:                 Money = "500"

  24:             });

  25:             salaryList.Add(new Salary()

  26:             {

  27:                 Name = "张三",

  28:                 Item = "应发工资",

  29:                 SubItem = "奖金",

  30:                 Month = "1月",

  31:                 Money = "130"

  32:             });

  33:             salaryList.Add(new Salary()

  34:             {

  35:                 Name = "张三",

  36:                 Item = "应发工资",

  37:                 SubItem = "奖金",

  38:                 Month = "1月",

  39:                 Money = "150"

  40:             });

  41:             salaryList.Add(new Salary()

  42:             {

  43:                 Name = "张三",

  44:                 Item = "应发工资",

  45:                 SubItem = "加班",

  46:                 Month = "1月",

  47:                 Money = "100"

  48:             });

  49:             salaryList.Add(new Salary()

  50:             {

  51:                 Name = "张三",

  52:                 Item = "应发工资",

  53:                 SubItem = "加班",

  54:                 Month = "1月",

  55:                 Money = "100"

  56:             });

  57:             salaryList.Add(new Salary()

  58:             {

  59:                 Name = "张三",

  60:                 Item = "五险一金",

  61:                 SubItem = "医疗保险",

  62:                 Month = "1月",

  63:                 Money = "500"

  64:             });

  65:             salaryList.Add(new Salary()

  66:             {

  67:                 Name = "张三",

  68:                 Item = "五险一金",

  69:                 SubItem = "住房公积金",

  70:                 Month = "1月",

  71:                 Money = "370"

  72:             });

  73:             salaryList.Add(new Salary()

  74:             {

  75:                 Name = "",

  76:                 Item = "",

  77:                 SubItem = "",

  78:                 Month = "合计",

  79:                 Money = "3500"

  80:             });

  81:             salaryList.Add(new Salary()

  82:             {

  83:                 Name = "张三",

  84:                 Item = "应发工资",

  85:                 SubItem = "基本工资",

  86:                 Month = "2月",

  87:                 Money = "3000"

  88:             });

  89:             salaryList.Add(new Salary()

  90:             {

  91:                 Name = "张三",

  92:                 Item = "应发工资",

  93:                 SubItem = "奖金",

  94:                 Month = "2月",

  95:                 Money = "400"

  96:             });

  97:             salaryList.Add(new Salary()

  98:             {

  99:                 Name = "张三",

 100:                 Item = "应发工资",

 101:                 SubItem = "奖金",

 102:                 Month = "2月",

 103:                 Money = "100"

 104:             });

 105:             salaryList.Add(new Salary()

 106:             {

 107:                 Name = "张三",

 108:                 Item = "应发工资",

 109:                 SubItem = "加班",

 110:                 Month = "2月",

 111:                 Money = "100"

 112:             });

 113:             salaryList.Add(new Salary()

 114:             {

 115:                 Name = "张三",

 116:                 Item = "应发工资",

 117:                 SubItem = "加班",

 118:                 Month = "2月",

 119:                 Money = "100"

 120:             });

 121:             salaryList.Add(new Salary()

 122:             {

 123:                 Name = "张三",

 124:                 Item = "应发工资",

 125:                 SubItem = "加班",

 126:                 Month = "2月",

 127:                 Money = "100"

 128:             });

 129:             salaryList.Add(new Salary()

 130:             {

 131:                 Name = "张三",

 132:                 Item = "五险一金",

 133:                 SubItem = "医疗保险",

 134:                 Month = "2月",

 135:                 Money = "500"

 136:             });

 137:             salaryList.Add(newSalary()

 138:             {

 139:                 Name = "张三",

 140:                 Item = "五险一金",

 141:                 SubItem = "住房公积金",

 142:                 Month = "2月",

 143:                 Money = "370"

 144:             });

 145:             salaryList.Add(new Salary()

 146:             {

 147:                 Name = "",

 148:                 Item = "",

 149:                 SubItem = "",

 150:                 Month = "合计",

 151:                 Money = "3900"

 152:             });

 153:             //----------------------------------------

 154:             salaryList.Add(new Salary()

 155:             {

 156:                 Name = "李四",

 157:                 Item = "应发工资",

 158:                 SubItem = "基本工资",

 159:                 Month = "1月",

 160:                 Money = "3000"

 161:             });

 162:             salaryList.Add(new Salary()

 163:             {

 164:                 Name = "李四",

 165:                 Item = "应发工资",

 166:                 SubItem = "奖金",

 167:                 Month = "1月",

 168:                 Money = "500"

 169:             });

 170:             salaryList.Add(new Salary()

 171:             {

 172:                 Name = "李四",

 173:                 Item = "应发工资",

 174:                 SubItem = "奖金",

 175:                 Month = "1月",

 176:                 Money = "130"

 177:             });

 178:             salaryList.Add(new Salary()

 179:             {

 180:                 Name = "李四",

 181:                 Item = "应发工资",

 182:                 SubItem = "奖金",

 183:                 Month = "1月",

 184:                 Money = "150"

 185:             });

 186:             salaryList.Add(new Salary()

 187:             {

 188:                 Name = "李四",

 189:                 Item = "应发工资",

 190:                 SubItem = "加班",

 191:                 Month = "1月",

 192:                 Money = "100"

 193:             });

 194:             salaryList.Add(new Salary()

 195:             {

 196:                 Name = "李四",

 197:                 Item = "应发工资",

 198:                 SubItem = "加班",

 199:                 Month = "1月",

 200:                 Money = "100"

 201:             });

 202:             salaryList.Add(new Salary()

 203:             {

 204:                 Name = "李四",

 205:                 Item = "五险一金",

 206:                 SubItem = "医疗保险",

 207:                 Month = "1月",

 208:                 Money = "500"

 209:             });

 210:             salaryList.Add(new Salary()

 211:             {

 212:                 Name = "李四",

 213:                 Item = "五险一金",

 214:                 SubItem = "住房公积金",

 215:                 Month = "1月",

 216:                 Money = "370"

 217:             });

 218:             salaryList.Add(new Salary()

 219:             {

 220:                 Name = "",

 221:                 Item = "",

 222:                 SubItem = "",

 223:                 Month = "合计",

 224:                 Money = "3500"

 225:             });

 226:             salaryList.Add(new Salary()

 227:             {

 228:                 Name = "李四",

 229:                 Item = "应发工资",

 230:                 SubItem = "基本工资",

 231:                 Month = "2月",

 232:                 Money = "3000"

 233:             });

 234:             salaryList.Add(new Salary()

 235:             {

 236:                 Name = "李四",

 237:                 Item = "应发工资",

 238:                 SubItem = "奖金",

 239:                 Month = "2月",

 240:                 Money = "400"

 241:             });

 242:             salaryList.Add(new Salary()

 243:             {

 244:                 Name = "李四",

 245:                 Item = "应发工资",

 246:                 SubItem = "奖金",

 247:                 Month = "2月",

 248:                 Money = "100"

 249:             });

 250:             salaryList.Add(newSalary()

 251:             {

 252:                 Name = "李四",

 253:                 Item = "应发工资",

 254:                 SubItem = "加班",

 255:                 Month = "2月",

 256:                 Money = "100"

 257:             });

 258:             salaryList.Add(new Salary()

 259:             {

 260:                 Name = "李四",

 261:                 Item = "应发工资",

 262:                 SubItem = "加班",

 263:                 Month = "2月",

 264:                 Money = "100"

 265:             });

 266:             salaryList.Add(new Salary()

 267:             {

 268:                 Name = "李四",

 269:                 Item = "应发工资",

 270:                 SubItem = "加班",

 271:                 Month = "2月",

 272:                 Money = "100"

 273:             });

 274:             salaryList.Add(new Salary()

 275:             {

 276:                 Name = "李四",

 277:                 Item = "五险一金",

 278:                 SubItem = "医疗保险",

 279:                 Month = "2月",

 280:                 Money = "500"

 281:             });

 282:             salaryList.Add(new Salary()

 283:             {

 284:                 Name = "李四",

 285:                 Item = "五险一金",

 286:                 SubItem = "住房公积金",

 287:                 Month = "2月",

 288:                 Money = "370"

 289:             });

 290:             salaryList.Add(new Salary()

 291:             {

 292:                 Name = "",

 293:                 Item = "",

 294:                 SubItem = "",

 295:                 Month = "合计",

 296:                 Money = "3900"

 297:             });

 298:             //-------------------------------------------

 299:             #endregion

 300:             Gridview1.DataSource =salaryList;

 301:             Gridview1.DataBind();

 302:            MergeGridViewCell.MergeRow(Gridview1, 0, 3);

 303:         }

 304:     }

 305: 

 306:     protectedvoid Gridview1_RowDataBound(object sender, GridViewRowEventArgs e)

 307:     {

 308:         if(e.Row.RowType == DataControlRowType.Header)

 309:         {

 310:             e.Row.BackColor =Color.FromArgb(135, 206, 250);

 311:         }

 312:         if(e.Row.RowType == DataControlRowType.DataRow)

 313:         {

 314:             if (e.Row.Cells[3].Text == "合计")

 315:             {

 316:                 e.Row.BackColor =Color.FromArgb(176, 226, 255);

 317:                e.Row.Cells[0].ColumnSpan = 4;

 318:                 e.Row.Cells[0].Text= "合计";

 319:                e.Row.Cells[1].Visible = e.Row.Cells[2].Visible = e.Row.Cells[3].Visible= false;

 320:             }

 321:         }

 322:     }

 323: }

 324: 

 325: public classSalary

 326: {

 327:     ///<summary>

 328:     /// 姓名

 329:     ///</summary>

 330:     publicstring Name { get; set; }

 331:     ///<summary>

 332:     /// 工资项

 333:     ///</summary>

 334:     publicstring Item { get; set; }

 335:     ///<summary>

 336:     /// 工资子项

 337:     ///</summary>

 338:     publicstring SubItem { get; set; }

 339:     ///<summary>

 340:     /// 月份

 341:     ///</summary>

 342:     publicstring Month { get; set; }

 343:     ///<summary>

 344:     /// 钱数

 345:     ///</summary>

 346:     publicstring Money { get; set; }

 347: }

GridView运行前后比较:


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现这样的功能,可以使用GridView控件的内置事件和属性。具体步骤如下: 1. 在GridView控件中设置属性`AutoGenerateColumns="false"`,手动添加列。 2. 为GridView控件绑定数据源。 3. 为GridView控件添加事件`RowDataBound`,在事件中为每一行的单元格添加`onkeydown`事件。 ```aspx <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowDataBound="GridView1_RowDataBound"> <Columns> <asp:BoundField DataField="Name" HeaderText="Name" /> <asp:BoundField DataField="Age" HeaderText="Age" /> <asp:BoundField DataField="Gender" HeaderText="Gender" /> </Columns> </asp:GridView> ``` ```csharp protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 绑定数据源 GridView1.DataSource = GetData(); GridView1.DataBind(); } } protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { // 为每一行的单元格添加onkeydown事件 foreach (TableCell cell in e.Row.Cells) { cell.Attributes.Add("onkeydown", "return MoveNextCell(event)"); } } } private DataTable GetData() { // 模拟数据 DataTable dt = new DataTable(); dt.Columns.Add("Name"); dt.Columns.Add("Age"); dt.Columns.Add("Gender"); dt.Rows.Add("Tom", "20", "Male"); dt.Rows.Add("Jerry", "18", "Female"); dt.Rows.Add("Alice", "22", "Female"); return dt; } ``` 4. 编写JavaScript函数`MoveNextCell`,在函数中判断按下的键是否是回车键,如果是则获取当前单元格的行和列,然后焦点移动到下一行同一列的单元格。 ```javascript function MoveNextCell(e) { var keyCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode; if (keyCode == 13) { // 回车键 var currentCell = e.srcElement || e.target; var currentRow = currentCell.parentNode.parentNode; var currentRowIndex = currentRow.rowIndex; var currentCellIndex = currentCell.cellIndex; var nextRow = currentRow.nextSibling; while (nextRow) { // 查找下一行 if (nextRow.nodeType == 1) { var nextCell = nextRow.cells[currentCellIndex]; if (nextCell) { // 如果存在同一列的单元格 nextCell.focus(); break; } } nextRow = nextRow.nextSibling; } return false; } return true; } ``` 通过以上步骤,就可以实现在GridView控件中获取当前单元格的焦点,按回车会获取下一行同一列的单元格焦点的功能了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值