Cor*_*oss 81 .net performance datagridview nvidia winforms
我的双显示器系统上的DataGridView遇到了一个非常奇怪的问题.该问题表现为对控件的极快重复(如完全重绘的30秒),但只有在我的某个屏幕上时才会显示.在另一方面,重绘速度很好.
我有一个Nvidia 8800 GT,带有最新的非beta驱动程序(175件).这是驱动程序错误吗?我会把它留在空中,因为我必须忍受这种特殊的配置.(它不会发生在ATI卡上,但......)
绘画速度与单元格内容无关,自定义绘图根本不会改善性能 - 即使只绘制实心矩形也是如此.
我后来发现在表单上放置一个ElementHost(来自System.Windows.Forms.Integration命名空间)可以解决问题.它不必被搞砸; 它只需要是DataGridView所在的表单的子级.只要Visible属性为true ,就可以将其大小调整为(0,0).
我不想明确地将.NET 3/3.5依赖项添加到我的应用程序中; 我创建了一个方法来在运行时创建此控件(如果可以)使用反射.它工作正常,至少它在没有所需库的机器上优雅地失败 - 它只是变得缓慢.
这个方法还允许我在应用程序运行时应用修复,这样可以更容易地看到WPF库在我的表单上发生了什么变化(使用Spy ++).
经过大量的试验和错误,我注意到在控件本身上启用双缓冲(而不仅仅是表单)可以解决问题!
因此,您只需要根据DataGridView创建一个自定义类,以便启用其DoubleBuffering.而已!
class CustomDataGridView: DataGridView
{
public CustomDataGridView()
{
DoubleBuffered = true;
}
}
Run Code Online (Sandbox Code Playgroud)
只要我的所有网格实例都使用这个自定义版本,一切都很好.如果我遇到由此引起的情况,我无法使用子类解决方案(如果我没有代码),我想我可以尝试将该控件注入表单:)(虽然我'将更有可能尝试使用反射来强制从外部启用DoubleBuffered属性再次避免依赖).
令人遗憾的是,这么简单的事情花了我很多时间......
Ben*_*oit 64
您只需要根据DataGridView创建一个自定义类,以便启用其DoubleBuffering.而已!
class CustomDataGridView: DataGridView
{
public CustomDataGridView()
{
DoubleBuffered = true;
}
}
Run Code Online (Sandbox Code Playgroud)
只要我的所有网格实例都使用这个自定义版本,一切都很好.如果我遇到由此引起的情况,我无法使用子类解决方案(如果我没有代码),我想我可以尝试将该控件注入表单:)(虽然我'将更有可能尝试使用反射来强制从外部启用DoubleBuffered属性再次避免依赖).
令人遗憾的是,这么简单的事情花了我很多时间......
注意:将答案作为答案,以便将问题标记为已回答
Bri*_*ink 59
下面是一些使用反射设置属性的代码,没有像Benoit建议的子类化.
typeof(DataGridView).InvokeMember(
"DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null,
myDataGridViewObject,
new object[] { true });
Run Code Online (Sandbox Code Playgroud)
GEL*_*ELR 16
对于在VB.NET中搜索如何操作的人,这里是代码:
DataGridView1.GetType.InvokeMember("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.SetProperty, Nothing, DataGridView1, New Object() {True})
Run Code Online (Sandbox Code Playgroud)
小智 8
添加到以前的帖子,对于Windows窗体应用程序,这是我用于DataGridView组件以使它们快速的.DrawingControl类的代码如下.
DrawingControl.SetDoubleBuffered(control)
DrawingControl.SuspendDrawing(control)
DrawingControl.ResumeDrawing(control)
Run Code Online (Sandbox Code Playgroud)
在构造函数中的InitializeComponent()之后调用DrawingControl.SetDoubleBuffered(control).
在进行大数据更新之前调用DrawingControl.SuspendDrawing(控件).
在进行大数据更新后调用DrawingControl.ResumeDrawing(控件).
最后2个最好用try/finally块完成.(或者甚至更好地重写类,IDisposable
并SuspendDrawing()
在构造函数ResumeDrawing()
中调用Dispose()
.)
using System.Runtime.InteropServices;
public static class DrawingControl
{
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
/// <summary>
/// Some controls, such as the DataGridView, do not allow setting the DoubleBuffered property.
/// It is set as a protected property. This method is a work-around to allow setting it.
/// Call this in the constructor just after InitializeComponent().
/// </summary>
/// <param name="control">The Control on which to set DoubleBuffered to true.</param>
public static void SetDoubleBuffered(Control control)
{
// if not remote desktop session then enable double-buffering optimization
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
{
// set instance non-public property with name "DoubleBuffered" to true
typeof(Control).InvokeMember("DoubleBuffered",
System.Reflection.BindingFlags.SetProperty |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic,
null,
control,
new object[] { true });
}
}
/// <summary>
/// Suspend drawing updates for the specified control. After the control has been updated
/// call DrawingControl.ResumeDrawing(Control control).
/// </summary>
/// <param name="control">The control to suspend draw updates on.</param>
public static void SuspendDrawing(Control control)
{
SendMessage(control.Handle, WM_SETREDRAW, false, 0);
}
/// <summary>
/// Resume drawing updates for the specified control.
/// </summary>
/// <param name="control">The control to resume draw updates on.</param>
public static void ResumeDrawing(Control control)
{
SendMessage(control.Handle, WM_SETREDRAW, true, 0);
control.Refresh();
}
}
Run Code Online (Sandbox Code Playgroud)
答案对我也有用.我想我会添加一个改进,我认为应该是实施解决方案的任何人的标准做法.
该解决方案很有效,除非在远程桌面下作为客户端会话运行UI,尤其是在可用网络带宽较低的情况下.在这种情况下,通过使用双缓冲可以使性能变差.因此,我建议以下作为更完整的答案:
class CustomDataGridView: DataGridView
{
public CustomDataGridView()
{
// if not remote desktop session then enable double-buffering optimization
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
DoubleBuffered = true;
}
}
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅检测远程桌面连接
归档时间: |
|
查看次数: |
43987 次 |
最近记录: |