在基于C#的Winform应用中,DataGridView和Listview作为数据的展示,应用十分广泛,而且,应用中基本上出现实时更新数据实现,做过这个应用的同学一定会碰到一个问题,那就是DataGridView和ListView更新每行数据时会出现闪烁。本质上,是这两个组件进行实时绘制造成的。那有什么办法解决这个问题呢?
其实,上述问题的解决本质上和C#反射无关,要解决DataGridView和ListView显示闪烁的问题,需要用到双缓冲,基本的原理就是,显示组件更新数据之前,先在缓冲中进行绘制,之后整体更新,这样更新的速度会很快,从而解决闪烁的问题。
那么如何使能DataGridView和ListView的双缓冲特性呢?
DataGridView 类 (System.Windows.Forms) | Microsoft Docs(Microsoft关于DataGridView的属性描述)中可以看到下面的描述:
DataGridView的DoubleBuffered属性
那我们是不是简单的调用DataGridView该属性,并且使能就可以了?事实上是不行的,因为DoubleBuffered属性是继承于Control组件,点开Control组件的DoubleBuffered属性就可以发现下面的描述:
Control组件的DoubleBuffered的属性描述
我们可以发现,DoubleBuffered属性的访问修饰符为protected,我们是不能直接在DataGridView直接使用该属性的,那怎么办呢?这里就用到了反射。
反射的应用可能是有很多,不过,我目前觉得比较好用的用途有两个:1,拿到一个陌生的类,我可以通过反射打印出它的方法,属性等;2,修改类中受保护的属性值。因此,DataGridView和ListView中的使能DoubleBuffered就用到了第2点。
反射在DataGridView和ListView的使用方法如下:(使能DoubleBuffered属性)
Type dgvType=this.DataGridView.GetType();//首先定义DataGridView的Type类
_PropertyInfo pi=dgvType.GetProperty(“DoubleBuffered”, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
//通过Type类,反射出DoubleBuffered的属性值。
//System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic:表示寻找的范围是示例成员以及非公开成员
pi.SetValue(this.DataGridView, true, null);//将DoubleBuffered属性值设置为True
通过上述方式就可以实现使能双缓冲的功能,另外说一句题外话,除了通过反射来实现外,还可以通过其他方式来实现,如新建DataGridView或者ListView类,如下图所示:
public class DoubleBufferedListView : System.Windows.Forms.ListView
{
public DoubleBufferedListView()
{
// 开启双缓冲
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
// Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form’s WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(Message m)
{
//Filter out the WM_ERASEBKGND message
if (m.Msg !=0x14)
{
base.OnNotifyMessage(m);
}
}
}
上述方式是直接对DoubleBuffered属性进行使能,已经不属于反射,本文不做更多叙述。
我们再说一下,反射的第一个用途,即可以打印陌生类证书的方法,属性,字段等,基本的调用方法如下:
type[] typearr=myassemby.Gettypes();//获取类型
foreach (type type in typearr)//针对每个类型获取详细信息
{
//获取类型的结构信息 cnblogs/sosoft/
_ConstructorInfo[] myconstructors=type.GetConstructors;
//获取类型的字段信息
_FieldInfo[] myfields=type.GetFiedls()
//获取方法信息
_MethodInfo myMethodInfo=type.GetMethods();
//获取属性信息
_PropertyInfo[] myproperties=type.GetProperties
//获取事件信息
_EventInfo[] Myevents=type.GetEvents;
}
这样就可以通过反射拿到这个类或者程序集的各种信息。
共同学习,写下你的评论
评论加载中...
作者其他优质文章