在DataGridView控件中实现冻结列分界线

我们在使用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;

        }
    }
时间: 2024-09-12 09:30:27

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

如何于DataGridView控件中以跨数据行方式显示数据

datagrid|控件|数据|显示 一般来说,每一个字段的内容会单独显示于DataGridView控件的一个数据行中.问题是,某些字段拥有大量文字数据,我是不是能够让该字段的内容以跨数据行的方式来显示,以便在有限的画面空间中的呈现出更完整的内容呢?答案当然是肯定的. 以图表1所示的执行画面而言,「自传」字段的内容并未单独显示于一个数据行中,而是以横跨数据行的方式,显示在同笔数据列之各字段内容的下方.相关程序代码列示如下: using System;using System.Collections

实现DataGridView控件中CheckBox列的使用实例

 最近做WindowsForms程序,使用DataGridView控件时,加了一列做选择用,发现CheckBox不能选中.搜索后,要实现DataGridView的CellContentClick事件,将代码贴一下 代码如下: /// <summary>         /// 实现DataGridView控件中CheckBox列的使用         /// </summary>         /// <param name="sender">&l

实现DataGridView控件中CheckBox列的使用实例_实用技巧

复制代码 代码如下: /// <summary>        /// 实现DataGridView控件中CheckBox列的使用        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void dgvTradList_Ce

c# winform-Winform中怎么设置DataGridView控件中的某个单元格为链接格式,不是整列。

问题描述 Winform中怎么设置DataGridView控件中的某个单元格为链接格式,不是整列. Winform中怎么设置DataGridView控件中的某个单元格为链接格式,不是整列.

在Visual Studio 2005的DataGridView控件中加入ComboBox下拉列表框的实现(C#)

datagrid|visual|控件|下拉|下拉列表 虽然在Visual Studio中 DataGridView控件的DataGridViewComboBoxColumn可以实现下拉列表框,但这样的列会在整列中都显示下拉列表框,不太美观,而且还要用代码实现数据绑定.本文介绍一种只在当前编辑单元格中显示下拉列表框的方法,供大家参考. 首先新建一个Windows应用程序,将主窗体重命名为MainForm,在MainForm中加入一个DataGridView控件,命名为dgv_User.如下图所示:

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

本文转载:http://www.cnblogs.com/luqingfei/archive/2007/03/28/691372.html   虽然在Visual Studio中 DataGridView控件的DataGridViewComboBoxColumn可以实现下拉列表框,但这样的列会在整列中都显示下拉列表框,不太美观,而且还要用代码实现数据绑定.本文介绍一种只在当前编辑单元格中显示下拉列表框的方法,供大家参考. 首先新建一个Windows应用程序,将主窗体重命名为MainForm,在Ma

小白请教个关于DataGridView控件中显示数据的问题。

问题描述 小白请教个关于DataGridView控件中显示数据的问题. private void button1_Click(object sender, EventArgs e) { SqlConnection conn = new SqlConnection("server = USER-20150322KM;database = huanghe;uid = sa; pwd = 121212"); SqlDataAdapter sda = new SqlDataAdapter(&q

winfrom datagridview 控件中 如何在修改、添加和删除后刷新数据?

问题描述 winfrom datagridview 控件中 如何在修改.添加和删除后刷新数据? winfrom datagridview 如何在修改.添加和删除之后如何刷新? 解决方案 http://blog.163.com/huang_ying_lu/blog/static/2699983201052971836350/ 解决方案二: datagridview.Remove这是自动删除一行,应该还有其他属性. 解决方案三: 你是在form上直接进行datagridview修改,删除,添加操作吗

【求助】如何打印DataGridView控件中显示的内容

问题描述 如何打印DataGridView控件中显示的内容,各位大虾有没有源代码示例一下! 解决方案 解决方案二:up解决方案三:up解决方案四:据我知道是截屏打印,在此把必要的代码附上.需要从工具箱中添加PringDocument在这里命名为pdusingSystem.Drawing.Printing;publicpartialclassI03_01:Baosight.iSuperFrame.Forms.FormBase{[System.Runtime.InteropServices.DllI