| 发表于:2007-02-10 16:10:54 楼主 |
这个实现,视觉效果方面基本上没有问题了,不过执行速度还有很大提升的空间(比如,我不加区分的每次画主标题就浪费了很多时间)。但引入timer控件的使用,刷新时闪烁的问题已经完美解决,本着“够用就行”的原则我不打算改进了... 代码:应该可以这样直接帖的,试试 /// <summary> /// 支持双行表头的的datagridview /// /// 用法示例: /// dg.addspanheader(4, 4, "主标题 "); /// 则将第4列开始的4列设为双行表头,主标题为“主标题”,子标题为原来的 value 值 /// /// phommy@hotmail.com /// </summary> public partial class datagridviewex1 : datagridview { public datagridviewex1() { initializecomponent(); } protected override void onpaint(painteventargs pe) { // todo: 在此处添加自定义绘制代码 // 调用基类 onpaint base.onpaint(pe); } private struct spaninfo //表头信息 { public spaninfo(string text, int position, int left, int right) { this.text = text; this.position = position; this.left = left; this.right = right; } public string text; //列主标题 public int position; //位置,1:左,2中,3右 public int left; //对应左行 public int right; //对应右行 } private dictionary <int, spaninfo> spanrows = new dictionary <int, spaninfo> ();//需要2维表头的列 public void addspanheader(int colindex, int colcount, string text) { if (colcount < 2) throw new exception( "行宽应大于等于2,合并1列无意义。 "); //检查范围 for (int i = 0; i < colcount; i++) { if (spanrows.containskey(colindex + i)) throw new exception( "单元格范围重叠! "); } //将这些列加入列表 int right = colindex + colcount - 1; //同一大标题下的最后一列的索引 spanrows[colindex] = new spaninfo(text, 1, colindex, right); //添加标题下的最左列 spanrows[right] = new spaninfo(text, 3, colindex, right); //添加该标题下的最右列 for (int i = colindex + 1; i < right; i++) //中间的列 { spanrows[i] = new spaninfo(text, 2, colindex, right); } } public void clearspaninfo() { spanrows.clear(); //redrawhead(); } private void datagridviewex_cellpainting(object sender, datagridviewcellpaintingeventargs e) { if (e.rowindex == -1) { if (spanrows.containskey(e.columnindex)) //被合并的列 { //画边框 graphics g = e.graphics; e.paint(e.cellbounds, datagridviewpaintparts.background ¦ datagridviewpaintparts.border); int left = e.cellbounds.left, top = e.cellbounds.top + 2, right = e.cellbounds.right, bottom = e.cellbounds.bottom; switch (spanrows[e.columnindex].position) { case 1: left += 2; break; case 2: break; case 3: right -= 2; break; } //画上半部分底色 g.fillrectangle(new solidbrush(e.cellstyle.backcolor), left, top, right - left, (bottom - top) / 2); //画中线 g.drawline(new pen(this.gridcolor), left, (top + bottom) / 2, right, (top + bottom) / 2); //写小标题 stringformat sf = new stringformat(); sf.alignment = stringalignment.center; sf.linealignment = stringalignment.center; g.drawstring(e.value + " ", e.cellstyle.font, brushes.black, new rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf); //写大标题 //if (this.spanrows[e.columnindex].position==3) { left = this.getcolumndisplayrectangle(spanrows[e.columnindex].left, true).left - 2; if (left < 0) left = this.getcelldisplayrectangle(-1, -1, true).width; right = this.getcolumndisplayrectangle(spanrows[e.columnindex].right, true).right - 2; if (right < 0) right = this.width; g.drawstring(spanrows[e.columnindex].text, e.cellstyle.font, brushes.black, new rectangle(left, top, right - left, (bottom - top) / 2), sf); } e.handled = true; } } } private void datagridviewex_scroll(object sender, scrolleventargs e) { if (e.scrollorientation == scrollorientation.horizontalscroll)// && e.type == scrolleventtype.endscroll) { timer1.enabled = false; timer1.enabled = true; } } //刷新显示表头 public void redrawhead() { foreach (int si in spanrows.keys) { this.invalidate(this.getcelldisplayrectangle(si, -1, true)); } } private void timer1_tick(object sender, eventargs e) { timer1.enabled = false; redrawhead(); }/// <summary> /// 必需的设计器变量。 /// </summary> private system.componentmodel.icontainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name= "disposing "> 如果应释放托管资源,为 true;否则为 false。 </param> protected override void dispose(bool disposing) { if (disposing && (components != null)) { components.dispose(); } base.dispose(disposing); } #region 组件设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void initializecomponent() { this.components = new system.componentmodel.container(); this.timer1 = new system.windows.forms.timer(this.components); ((system.componentmodel.isupportinitialize)(this)).begininit(); this.suspendlayout(); // // timer1 // this.timer1.interval = 20; this.timer1.tick += new system.eventhandler(this.timer1_tick); // // datagridviewex1 // this.rowtemplate.height = 23; this.cellpainting += new system.windows.forms.datagridviewcellpaintingeventhandler(this.datagridviewex_cellpainting); this.scroll += new system.windows.forms.scrolleventhandler(this.datagridviewex_scroll); ((system.componentmodel.isupportinitialize)(this)).endinit(); this.resumelayout(false); } #endregion private system.windows.forms.timer timer1; } |
|
|
|
|