Winforms: DataGridView的显示刷新问题 局部刷新

转载地址:https://blog.csdn.net/tqwer/article/details/7622413

一、 问题描述

向DataGridView大量插数据时,数据向下滚动会出现闪屏。

如果把DataGridView拖拽出显示屏的可视区域,然后再拖动滚动条显示DataGridView,我们发现表格里的数据刷新有问题而不能正常显示。

二、 问题重现

1. 在Vista或者Win7中,把主题设为Aero;

2. 在Visual Studio中创建一个Winforms工程;

3. 在Form1上添加一个DataGridView,并在属性(Properties)窗口为它添加三列;

4. 为Form1添加Load的事件相应器(Event Handler),并添加如下代码:

private void Form1_Load(object sender, EventArgs e)

{

for (int j = 0; j < 20; ++j)

{

    DataGridViewRow row = new DataGridViewRow();

    for (int i = 0; i < dataGridView1.Columns.Count; ++i)

    {

        DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();

        cell.Value = "Row: " + j.ToString() + " Column: " + i.ToString();

        row.Cells.Add(cell);

    }

    dataGridView1.Rows.Add(row);

}

}

5. 编译运行;

6. 把DataGridView中的横向滚动条拖到最右边;

7. 把Form1拖到屏幕的左边,让部分DataGridView不能显示;

8. 向左拖动DataGridView中的横向滚动条;

此时,DataGridView出现问题,表格里面的数据不能正常显示,如下图所示:

三、 问题分析

当我们向左拖动DataGridView的滚动条,让DataGridView左边之前在显示器可显示区域以外的数据时重新回到可显示的区域时,我们没有及时刷新这些区域。因此会出现显示重叠的问题。

四、 解决方案

Winforms将在.NET 4.0 SP1中解决掉这个问题。当.NET 4.0 SP1正式发布时,用户可以下载最新版本的.NET。

另外,由于问题出现的根源在于DataGridView在拖动滚动条没有及时刷新。因此只要我们只要在拖动滚动条时强制刷新以便能重新绘制DataGridView中的数据。此时该问题将迎刃而解。

基于这个思路,我们可以为例子中的dataGridView1添加一个Scroll事件相应器,并添加如下代码:

private void dataGridView1_Scroll(object sender, ScrollEventArgs e)

{

    dataGridView1.Invalidate();

}

上面这种方法固然简单。但当dataGridView1中的数据很多时,刷新整个区域将耗时很久,影响程序在拖动滚动条时的用户体验。我们需要一个性能更好的方案。

由于我们拖动滚动条时,只有一个很小的矩形区域是新出现在可显示区域的。如果我们仅仅只刷新这个很小的区域,性能将能得到极大的提升。于是,我们可以把代码改成:

private void dataGridView1_Scroll(object sender, ScrollEventArgs e)

{

        }

可以在程序构造写入

        SetStyle(ControlStyles.UserPaint, true);
        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.DoubleBuffer, true);


        Type dgvType = this.dataGridView1.GetType();
        PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(this.dataGridView1, true, null);

在控件事件中写入

private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
Rectangle rect;

        DataGridView ctrl = (DataGridView)sender;



        Point pt = PointToScreen(ctrl.Location);



        if (pt.X < 0)
        {

            int left = -pt.X;

            int top = ctrl.ColumnHeadersHeight;

            int width = e.OldValue - e.NewValue;

            int height = ctrl.ClientSize.Height;

            ctrl.Invalidate(new Rectangle(new Point(left, top), new Size(width, height)));

        }



        pt.X += ctrl.Width;

        rect = Screen.GetBounds(pt);



        if (pt.X > rect.Right)
        {

            int left = ctrl.ClientSize.Width - (pt.X - rect.Right) - (e.NewValue - e.OldValue);

            int top = ctrl.ColumnHeadersHeight;

            int width = e.NewValue - e.OldValue;

            int height = ctrl.ClientSize.Height;

            ctrl.Invalidate(new Rectangle(new Point(left, top), new Size(width, height)));

        }



        pt.Y += ctrl.Height;

        if (pt.Y > rect.Bottom)
        {

            int left = 0;

            int top = ctrl.ColumnHeadersHeight;

            int width = ctrl.ClientSize.Width;

            int height = ctrl.ClientSize.Height - (pt.Y - rect.Bottom) - (e.NewValue - e.OldValue);

            ctrl.Invalidate(new Rectangle(new Point(left, top), new Size(width, height)));

        }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值