我们在使用Office Excel的时候,有很多时候需要冻结行或者列。这时,Excel会在冻结的行列和非冻结的区域之间绘制上一条明显的黑线。如下图:

(图1)

WinForm下的DataGridView控件也能实现类似的冻结行或者列的功能(参见:http://msdn.microsoft.com/zh-cn/library/28e9w2e1(VS.85).aspx) ,但是呢,DataGridView控件默认不会在冻结列或者行的分界处绘制一个明显的分界线,这样的话,最终用户很难注意到当前有列或者行是冻结的。如下图所示:你能很快的找到那一列是Freeze的么?

(图2)

正是因为如此,我们如果能做出类似Excel的效果,就可以大大提高数据的可读性。

通常,我们如果想在现有的控件上多画点什么,就会去Override OnPaint方法,然后加入自己的OwnerDraw逻辑,但是呢在DataGridView上有一些困难:

1.如何确定冻结分界线的位置 
2.如何保证分界线不会绘制到ScrollBar上 
研究了一下,我们可以借用DataGridView提供的CellPainting方法。在DataGridView绘制每一个Cell的时候判断当前Cell是否是分界线所在的位置,然后进行绘制。最终做出的效果如下图:

(图3)

以下是DataGridView控件扩展源代码:

public class DataGridViewEx : DataGridView
{
    protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
    {
        base.OnCellPainting(e);
 
        //
        // Paints the Frozen line
        //
        int lastFreezeColumnIndex = GetDisplayColumnFrozenLineIndex();
        int lastFreezeRowIndex = GetDisplayRowFrozenLineIndex();
 
        bool drawRowLine = lastFreezeRowIndex != -1 && lastFreezeRowIndex == e.RowIndex;
        bool drawColumLine = lastFreezeColumnIndex != -1 && lastFreezeColumnIndex == e.ColumnIndex;
 
        if (drawRowLine || drawColumLine)
        {
            e.Paint(e.ClipBounds, e.PaintParts);
 
            if (drawColumLine)
            {
                e.Graphics.DrawLine(Pens.Black,
                    e.CellBounds.Right - 1, e.CellBounds.Top,
                    e.CellBounds.Right - 1, this.ClientRectangle.Bottom);
            }
            if (drawRowLine)
            {
                e.Graphics.DrawLine(Pens.Black,
                    e.CellBounds.Left, e.CellBounds.Bottom - 1,
                    e.CellBounds.Right, e.CellBounds.Bottom - 1);
            }
 
            e.Handled = true;
        }
    }
 
    private int GetDisplayColumnFrozenLineIndex()
    {
        int lastFreezeColumnIndex = -1;
        for (int i = 0; i < this.ColumnCount; i++)
        {
            DataGridViewColumn column = this.Columns[i];
            if (column.Visible && column.Frozen)
            {
                lastFreezeColumnIndex = i;
            }
            else if (!column.Frozen)
            {
                return lastFreezeColumnIndex;
            }
        }
        return lastFreezeColumnIndex;
    }
 
    private int GetDisplayRowFrozenLineIndex()
    {
        int lastFreezeRowIndex = -1;
        for (int i = 0; i < this.RowCount; i++)
        {
            DataGridViewRow row = this.Rows[i];
            if (row.Visible && row.Frozen)
            {
                lastFreezeRowIndex = i;
            }
            else if (!row.Frozen)
            {
                return lastFreezeRowIndex;
            }
        }
        return lastFreezeRowIndex;
 
    }
}

在DataGridView控件中实现冻结列分界线的更多相关文章

  1. 实现DataGridView控件中CheckBox列的使用

    最近做WindowsForms程序,使用DataGridView控件时,加了一列做选择用,发现CheckBox不能选中.搜索后,要实现DataGridView的CellContentClick事件,将 ...

  2. 在DataGridView控件中加入ComboBox下拉列表框的实现

    在DataGridView控件中加入ComboBox下拉列表框的实现 转自:http://www.cnblogs.com/luqingfei/archive/2007/03/28/691372.htm ...

  3. 在DataGridView控件中验证数据输入

    实现效果: 知识运用: DataGridView控件的公共事件CellValidating //将System.Windows.Forms.DataGridViewCellValidatingEven ...

  4. DataGridView控件中添加ComboBox下拉列表框的实现

    //ComboBox控件拖放到DataGridView控件的某个位置 //添加年龄下拉框 private void BindAge() { //我这里添加的是静态数据,一般都是从数据库读出来的,这里就 ...

  5. 在DataGridView控件中显示图片

    实现效果: 知识运用: DataGridView控件的DataSource属性 实现代码: private void Form1_Load(object sender, EventArgs e) { ...

  6. 禁止DataGridView控件中添加和删除行

    实现效果: 知识运用: DataGridView控件的AllowUserToAddRows AllowUserDeleteRows和ReadOnly属性 实现代码: private void btn_ ...

  7. 在DataGridView控件中启用换行

    实现效果: 知识运用: DataGridView控件公共属性DefaultCellStyle的WrapMode属性 public DataGridViewTriState WrapMode {  ge ...

  8. 设置DataGridView控件中字体的样式

    实现效果: 知识运用: DataGridView控件的公共属性DefaultCellStyle的Font属性 public Font Font  {get;set;} //获取或设置应用与DataGr ...

  9. 如何在winform DataGridView控件的DataGridViewButtonColumn按钮列中禁用按钮

    原文:http://msdn.microsoft.com/en-us/library/ms171619(v=vs.85).ASPX public class DataGridViewDisableBu ...

随机推荐

  1. APP版本升级

    /*** version_upgrade 版本升级信息表*/CREATE TABLE `version_upgrade` ( `id` smallint(4) unsigned NOT NULL AU ...

  2. 逻辑回归(Logistic Regression)算法小结

    一.逻辑回归简述: 回顾线性回归算法,对于给定的一些n维特征(x1,x2,x3,......xn),我们想通过对这些特征进行加权求和汇总的方法来描绘出事物的最终运算结果.从而衍生出我们线性回归的计算公 ...

  3. 九度oj 题目1499:项目安排

    题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的.由于小明马上就要硕士毕业了,面临着买房.买车.给 ...

  4. 2.ruby基本语法,类的定义

    1.在ruby中的定义class,ruby中定义类也是以关键字class开头 后面带着类名,类名以大写开头.一个类的结束以关键字end 结束.如: class Customer end 2.ruby类 ...

  5. HackerRank# Bricks Game

    原题地址 DP很简单,懒得压缩空间了,反正都能过 #include <cmath> #include <cstdio> #include <vector> #inc ...

  6. 648. Replace Words

    Problem statement In English, we have a concept called root, which can be followed by some other wor ...

  7. Merge into语句用法及其效率问题

    Merge into语句用法及其效率问题 /*Merge into 详细介绍MERGE语句用来合并UPDATE和INSERT语句.通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询, ...

  8. angular父子scope之间的访问

    1.子可以访问父的scope,也可以更新相同的scope,但父scope不会被刷新 2.父要访问子scope的方法

  9. LA 4973异面线段

    题目大意:给两条线段求他们间的最小距离的平方(以分数形式输出). 贴个模版吧!太抽象了. #include<cstdio> #include<cmath> #include&l ...

  10. poj 1031 多边形对点(向周围发射光线)的覆盖

    Fence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3018   Accepted: 1010 Description ...