나는 실제로 이것을 해결했지만 후세를 위해 게시하고 있습니다.
듀얼 모니터 시스템에서 DataGridView에 매우 이상한 문제가 발생했습니다. 이 문제는 컨트롤의 매우 느린 다시 그리기로 나타납니다 ( 전체 다시 그리기의 경우 30 초 정도 ).하지만 내 화면 중 하나에있을 때만 나타납니다. 다른 경우에는 다시 그리기 속도가 좋습니다.
최신 비 베타 드라이버 (175. 무언가)가있는 Nvidia 8800 GT가 있습니다. 드라이버 버그입니까? 이 특정 구성으로 살아야하므로 공중에 남겨 두겠습니다. (하지만 ATI 카드에서는 발생하지 않습니다 …)
페인트 속도는 셀 내용과 관련이 없으며 사용자 정의 드로잉은 단색 사각형을 그리는 경우에도 성능을 전혀 향상시키지 않습니다.
나중에 System.Windows.Forms.Integration 네임 스페이스의 ElementHost를 폼에 배치하면 문제가 해결된다는 사실을 알게되었습니다. 엉망이 될 필요는 없습니다. DataGridView도있는 형식의 자식이어야합니다. Visible 속성이 true이면 크기를 (0, 0)으로 조정할 수 있습니다 .
내 응용 프로그램에 .NET 3 / 3.5 종속성을 명시 적으로 추가하고 싶지 않습니다. 리플렉션을 사용하여 런타임시 (가능한 경우)이 컨트롤을 만드는 방법을 만듭니다. 작동하고 최소한 필요한 라이브러리가없는 머신에서는 정상적으로 실패합니다. 단지 느려진 상태로 돌아갑니다.
이 방법을 사용하면 앱이 실행되는 동안 수정을 적용 할 수 있으므로 내 양식에서 WPF 라이브러리가 변경되는 내용을 쉽게 확인할 수 있습니다 (Spy ++ 사용).
많은 시행 착오 끝에 컨트롤 자체에서 이중 버퍼링을 활성화하면 (단지 형식이 아닌) 문제가 해결된다는 것을 알았습니다!
따라서 DoubleBuffering을 활성화 할 수 있도록 DataGridView를 기반으로 사용자 지정 클래스를 만들기 만하면됩니다. 그게 다야!
class CustomDataGridView: DataGridView
{
public CustomDataGridView()
{
DoubleBuffered = true;
}
}
그리드의 모든 인스턴스가이 사용자 정의 버전을 사용하는 한 모두 정상입니다. 이로 인해 하위 클래스 솔루션을 사용할 수없는 상황이 발생하면 (코드가없는 경우) 해당 컨트롤을 폼에 삽입 할 수 있다고 가정합니다. 🙂 ( ‘I 있지만, 다시 한 번 종속성을 피하기 위해 DoubleBuffered 속성을 외부에서 강제로 사용하도록 리플렉션을 사용하려고 시도 할 가능성이 더 높습니다 .
그렇게 사소한 일이 내 시간을 너무 많이 먹은 것이 슬프다 …
답변
DoubleBuffering을 활성화 할 수 있도록 DataGridView를 기반으로 사용자 지정 클래스를 만들기 만하면됩니다. 그게 다야!
class CustomDataGridView: DataGridView
{
public CustomDataGridView()
{
DoubleBuffered = true;
}
}
그리드의 모든 인스턴스가이 사용자 정의 버전을 사용하는 한 모두 정상입니다. 이로 인해 하위 클래스 솔루션을 사용할 수없는 상황이 발생하면 (코드가없는 경우) 해당 컨트롤을 폼에 삽입 할 수 있다고 가정합니다. 다시 한 번 종속성을 피하기 위해 DoubleBuffered 속성을 외부에서 강제로 사용하기 위해 리플렉션을 사용하려고 시도 할 가능성이 더 높습니다).
그렇게 사소한 일이 내 시간을 너무 많이 먹은 것이 슬프다 …
참고 : 질문이 답변 됨으로 표시 될 수 있도록 답변하기
답변
다음은 Benoit이 제안한대로 서브 클래 싱없이 리플렉션을 사용하여 속성을 설정하는 코드입니다.
typeof(DataGridView).InvokeMember(
"DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null,
myDataGridViewObject,
new object[] { true });
답변
VB.NET에서 수행하는 방법을 검색하는 사람들을 위해 다음 코드가 있습니다.
DataGridView1.GetType.InvokeMember("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.SetProperty, Nothing, DataGridView1, New Object() {True})
답변
이전 게시물에 추가하여 Windows Forms 응용 프로그램의 경우 DataGridView 구성 요소를 빠르게 만들기 위해 사용합니다. DrawingControl 클래스의 코드는 다음과 같습니다.
DrawingControl.SetDoubleBuffered(control)
DrawingControl.SuspendDrawing(control)
DrawingControl.ResumeDrawing(control)
생성자에서 InitializeComponent () 다음에 DrawingControl.SetDoubleBuffered (control)를 호출합니다.
빅 데이터 업데이트를 수행하기 전에 DrawingControl.SuspendDrawing (control)을 호출하십시오.
빅 데이터 업데이트 후 DrawingControl.ResumeDrawing (control)을 호출합니다.
마지막 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();
}
}
답변
이것에 대한 대답은 나에게도 효과적이었습니다. 솔루션을 구현하는 모든 사람에게 표준 관행이되어야한다고 생각하는 개선 사항을 추가 할 것이라고 생각했습니다.
이 솔루션은 UI가 원격 데스크톱에서 클라이언트 세션으로 실행되는 경우, 특히 사용 가능한 네트워크 대역폭이 낮은 경우를 제외하고는 잘 작동합니다. 이 경우 이중 버퍼링을 사용하면 성능이 저하 될 수 있습니다. 따라서 더 완전한 대답으로 다음을 제안합니다.
class CustomDataGridView: DataGridView
{
public CustomDataGridView()
{
// if not remote desktop session then enable double-buffering optimization
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
DoubleBuffered = true;
}
}
자세한 내용은 원격 데스크톱 연결 감지를 참조하십시오.
답변
문제에 대한 해결책을 찾았습니다. 고급 디스플레이 속성의 문제 해결 탭으로 이동하여 하드웨어 가속 슬라이더를 확인하십시오. IT에서 새 회사 PC를 받았을 때 전체에서 1 틱으로 설정되었고 데이터 그리드에 문제가 없었습니다. 비디오 카드 드라이버를 업데이트하고 전체로 설정하면 데이터 그리드 컨트롤의 페인팅이 매우 느려졌습니다. 그래서 나는 그것을 원래 위치로 재설정하고 문제가 사라졌습니다.
이 트릭이 당신에게도 효과가 있기를 바랍니다.
답변
이 문제를 해결하기 위해 수행 한 작업을 추가하기 위해 최신 Nvidia 드라이버로 업그레이드하여 문제를 해결했습니다. 코드를 다시 작성할 필요가 없습니다.
완성도를 위해 카드는 2008 년 3 월 (v. 169) 드라이버가있는 Nvidia Quadro NVS 290이었습니다. 최신 버전 (v. 182, 2009 년 2 월)으로 업그레이드하면 모든 컨트롤, 특히 DataGridView의 그리기 이벤트가 크게 향상되었습니다.
이 문제는 개발이 발생하는 ATI 카드에서 발견되지 않았습니다.