• 全部
...

再散一帖:关于双行表头的的DataGridView的实现

phommy 2007-02-10 04: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;
}
...全文
给本帖投票
1546 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangluozhuanqian 2010-07-30
  • 打赏
  • 举报
回复
我的最新多表头 DATAGRIDVIEW 多表头 合计行 C# 汇总行 汇总列 自动计算列 http://big5.gov.cn/gate/big5/t.wz265.com/index.asp?id=11046
readfuture 2010-02-08
  • 打赏
  • 举报
回复
d
paulin 2008-01-15
  • 打赏
  • 举报
回复
学习~~~
jinglong6511 2007-02-12
  • 打赏
  • 举报
回复
好东西
「已注销」 2007-02-12
  • 打赏
  • 举报
回复
up
xk000 2007-02-11
  • 打赏
  • 举报
回复
学习中... 欢迎加入ASP.NET(C#)学习交流QQ群号:①32801051(已满) ②23222074(请不要两个群都加)
HarleyTung 2007-02-11
  • 打赏
  • 举报
回复
学习,接分!
lizhizhe2000 2007-02-11
  • 打赏
  • 举报
回复
学习!
lao_bulls 2007-02-11
  • 打赏
  • 举报
回复
学习
xiaoliangwh 2007-02-11
  • 打赏
  • 举报
回复
up

阿牛138588 2007-02-10
  • 打赏
  • 举报
回复
学习
心晴Sunheart 2007-02-10
  • 打赏
  • 举报
回复
终于解决了??!!
呵呵
xiaotupansy 2007-02-10
  • 打赏
  • 举报
回复
好东西
up

111,092

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧

手机看
关注公众号

关注公众号

客服 返回
顶部