我们在使用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. BZOJ 3028 食物 ——生成函数

    把所有东西的生成函数搞出来. 发现结果是x*(1-x)^(-4) 然后把(1-x)^(-4)求逆,得到(1+x+x^2+...)^4 然后考虑次数为n的项前的系数,就相当于选任意四个非负整数构成n的方 ...

  2. weixin-api生成二维码

    二维码长链接转成短链接(减少扫描时间和提高成功率) 微信返回正确的二维码的结果,参数有个url,即二维码图片解析后的地址,也可以根据此URL生成需要的二维码图片,而不需要通过ticket去换取图片了 ...

  3. C 语言中可以调用命令行指令的 system()函数

    C语言有一个system函数(在<stdlib.h>头中,C++则为<cstdlib>头),可以用来调用终端命令.原型如下: int system(const char *cm ...

  4. cf487C Prefix Product Sequence

    Consider a sequence [a1, a2, ... , an]. Define its prefix product sequence . Now given n, find a per ...

  5. Error处理: “非法字符: \65279”的解决办法

    将eclipse项目转为maven项目的时候,编译时遇到 “非法字符: \65279”的报错. 出错内容是: *.java:1: 非法字符: \65279    [javac] package com ...

  6. django搭建开发环境

    1.安装python,安装pip,添加环境变量 2.使用虚拟环境Virtualenv,下载virtualenv解压,进入到此目录,cmd运行python setup.py install(或直接打开c ...

  7. 最短路中部分点只能从中任意选取K个问题

    题意:给N个点,还有另外m个点(其中只能选K个),求最短路. 思路:在SPFA的基础上,用一个数组来统计,在某点入队时(要拓展其他点了),若该点是m个点中的,则count[i]=原来的+1:若不是,则 ...

  8. Codeforces 959 D Mahmoud and Ehab and another array construction task

    Discription Mahmoud has an array a consisting of n integers. He asked Ehab to find another arrayb of ...

  9. MD5加密算法Java代码

    原文:http://www.open-open.com/code/view/1428398234916 import java.security.MessageDigest; import java. ...

  10. Java8 本地DateTime API

    原文:http://www.yiibai.com/java8/java8_localdateapi.html 使用Java8,新的日期时间API引入覆盖旧的日期时间API的以下缺点. 非线程安全 - ...