Soru İki ekranımdan birinde DataGridView'ın korkunç yeniden çizme performansı


Bunu gerçekten çözdüm, ama onu posterciliğe gönderiyorum.

Çift monitör sistemimde DataGridView ile çok garip bir sorun yaşadım. Sorun, kontrolün son derece yavaş bir yeniden boyaması olarak kendini gösteriyor.tam bir rötuş için 30 saniye gibi), ancak sadece ekranlarımdan birinde olduğunda. Diğer tarafta, rötuş hızı iyi.

En yeni beta olmayan sürücülerle (175. bir şey) Nvidia 8800 GT'm var. Sürücü hatası mı? Bu özel konfigürasyonla yaşamak zorunda olduğum için bunu havada bırakacağım. (ATI kartlarında olmasa da ...)

Boya hızının hücre içeriği ile hiçbir ilgisi yoktur ve özel çizim, sadece bir katı dikdörtgeni boyadığında bile performansı iyileştirmez.

Daha sonra formda bir ElementHost (System.Windows.Forms.Integration ad alanı) yerleştirme sorunu düzeltir buluyorum. Bununla uğraşmak zorunda değil; Sadece DataGridView'ın da olduğu formdaki bir çocuğun olması gerekiyor. Bu sürece (0, 0) için yeniden boyutlandırılabilir Gözle görülür özellik doğrudur.

.NET 3 / 3.5 bağımlılığını uygulamanıza açıkça eklemek istemiyorum; Yansıma kullanarak çalışma zamanında (eğer yapabilirse) bu denetimi oluşturmak için bir yöntem yapıyorum. İşe yarıyor ve en azından gerekli kütüphaneye sahip olmayan makinelerde incelikle başarısız oluyor - bu sadece yavaş olmaya geri dönüyor.

Bu yöntem aynı zamanda uygulama çalışırken düzeltmek için başvurmamı sağlar, WPF kitaplıklarının formumda (Spy ++ kullanarak) neler değiştiğini görmeyi kolaylaştırır.

Çok fazla deneme ve hatadan sonra, kontrolün kendisinde (sadece formun tersine) çift arabelleğe almanın problemi düzelttiğini fark ettim!


Dolayısıyla, sadece DoubleGuffering'i etkinleştirebilmeniz için DataGridView'a dayalı özel bir sınıf oluşturmanız gerekir. Bu kadar!

class CustomDataGridView: DataGridView
{
    public CustomDataGridView()
    {
        DoubleBuffered = true;
    }
}

Kılavuzun tüm örnekleri bu özel sürümü kullandığı sürece, her şey yolunda. Eğer alt sınıf çözümünü kullanamadığım bir durumla karşılaşırsam (eğer kodum yoksa), bu kontrolü forma enjekte etmeyi deneyebilirim :) (DoubleBuffered özelliğini dışarıdan bir kez daha zorlamak için yansımayı kullanmayı denemeye daha yatkın olmasına rağmen bağımlılığı önlemek).

Bu kadar basit ve basit bir şeyin zamanımın çoğunu yemesi çok üzücü ...


76
2017-09-23 01:01


Menşei


Müşterilerimizle benzer bir sorun yaşadık multimon Kurulmuş. Hangi nedenle olursa olsun, Multimon'u kapattığında, sorun gider. - BlueRaja - Danny Pflughoeft


Cevaplar:


Sadece DoubleGuffering'i etkinleştirebilmeniz için DataGridView'a dayalı özel bir sınıf oluşturmanız gerekir. Bu kadar!


class CustomDataGridView: DataGridView
{
    public CustomDataGridView()
    {
        DoubleBuffered = true;
    } 
}

Kılavuzun tüm örnekleri bu özel sürümü kullandığı sürece, her şey yolunda. Eğer alt sınıf çözümünü kullanamadığım bir durumla karşılaşırsam (eğer kodum yoksa), bu kontrolü forma enjekte etmeyi deneyebilirim :) (yine de DoubleBuffered özelliğini dışarıdan bir kez daha bağımlılıktan kaçınmaya zorlamak için yansıma kullanmayı denemesi daha olasıdır).

Bu kadar basit ve basit bir şeyin zamanımın çoğunu yemesi çok üzücü ...

Not: Cevabı bir cevap olarak vermek, böylece soru cevap olarak işaretlenebilir


60
2017-10-01 19:49



WPF için Windows Forms Entegrasyonu ile bunu nasıl yapabilirsiniz? - Partial
Cevap için teşekkürler. Alt sınıf çözümünü bazen nasıl kullanamazsınız? ("Kodu yoksa" diye anlayamadım). - Dan W
Fantastik! Projemde hem masanın üzerinde hem de masanın üzerinde duran garip yavaşlamadan kaynaklanan çekicilik gibi çalışıyor (: - knut


Burada, Benoit'in öne sürdüğü gibi, alt sınıflandırma yapılmadan yansımayı kullanarak mülkiyeti belirleyen bazı kodlar var.

typeof(DataGridView).InvokeMember(
   "DoubleBuffered", 
   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
   null, 
   myDataGridViewObject, 
   new object[] { true });

58
2018-04-24 18:52



Yardım ettiğim için sevindim! Neredeyse hiç yayınlamadım çünkü bu soru zaten bir yaşındaydı. - Brian Ensink
Neah, gelecekte her zaman, belki de bu konuyu Google'dan alan, belki de ben gibi birilerine yardımcı olacaktır. Teşekkürler! Btw, bunu Form1_Load bölümüne koymak tercih edilir mi? - Dan W
Sadece bu fikri anlayan başka birine vermek için: Bu yararlı bir uzantı yöntemidir. Control sınıf. public static void ToggleDoubleBuffered(this Control control, bool isDoubleBuffered). - Anthony


VB.NET'te nasıl yapılacağını araştıran kişiler için kod aşağıdadır:

DataGridView1.GetType.InvokeMember("DoubleBuffered", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.SetProperty, Nothing, DataGridView1, New Object() {True})

13
2018-05-18 15:15





Windows Forms uygulamaları için önceki yayınlara eklediğimizde, bunları hızlı hale getirmek için DataGridView bileşenleri için kullanıyorum. DrawingControl sınıfının kodu aşağıdadır.

DrawingControl.SetDoubleBuffered(control)
DrawingControl.SuspendDrawing(control)
DrawingControl.ResumeDrawing(control)

Yapıcıdaki InitializeComponent () öğesinden sonra DrawingControl.SetDoubleBuffered (denetim) arayın.

Büyük veri güncellemeleri yapmadan önce DrawingControl.SuspendDrawing (kontrol) çağırın.

Büyük veri güncellemeleri yaptıktan sonra DrawingControl.ResumeDrawing (kontrol) çağırın.

Bu son 2 en iyi bir deneme / sonuncu blok ile yapılır. (veya sınıfı daha iyi yeniden yaz IDisposable ve Çağrı yap SuspendDrawing() kurucu ve ResumeDrawing() içinde 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();
    }
}

7
2018-04-13 16:45





Bunun cevabı benim için de işe yaradı. Çözümü uygulayan herkes için standart bir uygulama olması gerektiğini düşündüğüm bir ayrıntı ekleyeceğimi düşündüm.

Çözüm, UI'nin, özellikle mevcut ağ bant genişliğinin düşük olduğu durumlarda, uzak masaüstünde bir istemci oturumu olarak çalıştırılması dışında iyi çalışır. Böyle bir durumda, çift arabelleğin kullanımıyla performans daha da kötüleştirilebilir. Bu nedenle, aşağıdakileri daha eksiksiz bir yanıt olarak öneririm:

class CustomDataGridView: DataGridView
{
    public CustomDataGridView()
    {
        // if not remote desktop session then enable double-buffering optimization
        if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
            DoubleBuffered = true;
    } 
}

Daha fazla bilgi için bkz. Uzak masaüstü bağlantısının algılanması


6
2017-10-07 20:28





Soruna bir çözüm buldum. Gelişmiş görüntü özelliklerinde sorun giderme sekmesine gidin ve donanım hızlandırma kaydırıcısını kontrol edin. Yeni şirket bilgisayarımı BT'den aldığımda, tam olarak bir kene olarak ayarlandı ve datagrids ile ilgili herhangi bir sorun yaşamadım. Bir kez ekran kartı sürücüsünü güncelledim ve tam olarak ayarladıktan sonra, datagrid kontrollerinin boyaması çok yavaşladı. Böylece, bulunduğu yere geri sıfırladım ve sorun ortadan kalktı.

Umarım bu hile de sizin için çalışır.


1
2018-02-26 22:35





Sadece bu sorunu çözmek için yaptığımız şeyi eklemek için: En son Nvidia sürücülerine güncelledik, sorunu çözdük. Hiçbir kodun yeniden yazılması gerekmedi.

Tamlık için, kart Mart 2008 tarihli (v. 169) sürücülere sahip bir Nvidia Quadro NVS 290 idi. En son sürüme (v. 182 Şubat 2009 tarihli) yükseltmek, tüm denetimlerim için özellikle de DataGridView için boya olaylarını önemli ölçüde geliştirdi.

Bu sorun herhangi bir ATI kartında görülmedi (geliştirmenin gerçekleştiği yer).


1
2018-06-10 16:54





En iyi!:

Private Declare Function SendMessage Lib "user32" _
  Alias "SendMessageA" _
  (ByVal hWnd As Integer, ByVal wMsg As Integer, _
  ByVal wParam As Integer, ByRef lParam As Object) _
  As Integer

Const WM_SETREDRAW As Integer = &HB

Public Sub SuspendControl(this As Control)
    SendMessage(this.Handle, WM_SETREDRAW, 0, 0)
End Sub

Public Sub ResumeControl(this As Control)
    RedrawControl(this, True)
End Sub

Public Sub RedrawControl(this As Control, refresh As Boolean)
    SendMessage(this.Handle, WM_SETREDRAW, 1, 0)
    If refresh Then
        this.Refresh()
    End If
End Sub

1
2017-10-07 19:45





Bir çift monitör sisteminde .NET 3.0 ve DataGridView kullanarak benzer bir sorun yaşadık.

Uygulamamız, gri bir arka plan ile ızgarayı gösterecek ve bu da hücrelerin değiştirilemeyeceğini gösteriyor. Bir "ayarları değiştir" düğmesini seçtikten sonra, program, hücre metninin değiştirilebileceğini kullanıcıya göstermek için beyazın arka plan rengini değiştirecektir. Bir "iptal" düğmesi, daha önce bahsedilen hücrelerin arka plan rengini griye değiştirecektir.

Arka plan rengi değiştikçe, aynı sayıda satır ve sütuna sahip bir varsayılan boyutlu ızgaraya kısa bir izlenim olacaktı. Bu sorun sadece birincil monitörde (asla ikincil olmayan) ortaya çıkar ve tek bir monitör sisteminde gerçekleşmez.

Yukarıdaki örneği kullanarak kontrolün iki kez tamponlanması problemimizi çözdü. Yardımınızı çok takdir ediyoruz.


0