2010-08-01 2 views
3

Я использую ListView в VirtualMode и Details View с небольшими значками.WinForms ListView рисует HELL SLOW в Windows 7 по сравнению с XP

Этот ListView имеет 100 000 элементов внутри.

Проблема заключается в том, что рисунок этого списка намного медленнее в Windows 7 по сравнению с XP.

Вы можете заполнить медленный чертеж, прокручивая ListView или в то время как многопозиционные элементы.

Кроме того, я заметил, что рисунок становится медленнее с каждым добавленным столбцом.

Обработчик события RetrieveVirtualItem теперь ничего не делает, кроме возвращаемых значений, поэтому это не является узким местом.

Любые идеи?

UPDATE: Исходный код для воспроизведите:

FlickerFreeListView.cs:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.ComponentModel; 
using System.Drawing; 
using System.Reflection; 
using System.Diagnostics; 

namespace ListViewTest 
{ 
    public class FlickerFreeListView : ListView 
    { 
     public FlickerFreeListView() 
     { 
      base.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 
     } 
    } 
} 

Form1.cs:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Diagnostics; 

namespace ListViewTest 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 

      _item = new ListViewItem(new string[6]); 
     } 

     private ListViewItem _item; 

     private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
     { 
      string itemIndexStr = e.ItemIndex.ToString(); 
      _item.Text = itemIndexStr; 
      _item.SubItems[1].Text = "blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla"; 
      _item.SubItems[2].Text = itemIndexStr; 
      _item.SubItems[3].Text = itemIndexStr; 
      _item.SubItems[4].Text = itemIndexStr; 
      _item.SubItems[5].Text = itemIndexStr; 
      e.Item = _item; 
     } 
    } 
} 

Form1.Designer.cs:

namespace ListViewTest 
{ 
    partial class Form1 
    { 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.listView1 = new ListViewTest.FlickerFreeListView(); 
      this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); 
      this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); 
      this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); 
      this.columnHeader4 = new System.Windows.Forms.ColumnHeader(); 
      this.columnHeader5 = new System.Windows.Forms.ColumnHeader(); 
      this.columnHeader6 = new System.Windows.Forms.ColumnHeader(); 
      this.SuspendLayout(); 
      // 
      // listView1 
      // 
      this.listView1.AutoArrange = false; 
      this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 
     this.columnHeader1, 
     this.columnHeader2, 
     this.columnHeader3, 
     this.columnHeader4, 
     this.columnHeader5, 
     this.columnHeader6}); 
      this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; 
      this.listView1.FullRowSelect = true; 
      this.listView1.HideSelection = false; 
      this.listView1.Location = new System.Drawing.Point(0, 0); 
      this.listView1.Name = "listView1"; 
      this.listView1.Size = new System.Drawing.Size(1032, 388); 
      this.listView1.TabIndex = 0; 
      this.listView1.UseCompatibleStateImageBehavior = false; 
      this.listView1.View = System.Windows.Forms.View.Details; 
      this.listView1.VirtualListSize = 100000; 
      this.listView1.VirtualMode = true; 
      this.listView1.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.listView1_RetrieveVirtualItem); 
      // 
      // columnHeader1 
      // 
      this.columnHeader1.Width = 92; 
      // 
      // columnHeader2 
      // 
      this.columnHeader2.Width = 405; 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(1032, 388); 
      this.Controls.Add(this.listView1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.WindowState = System.Windows.Forms.FormWindowState.Maximized; 
      this.ResumeLayout(false); 

     } 

     #endregion 

     private FlickerFreeListView listView1; 
     private System.Windows.Forms.ColumnHeader columnHeader1; 
     private System.Windows.Forms.ColumnHeader columnHeader2; 
     private System.Windows.Forms.ColumnHeader columnHeader3; 
     private System.Windows.Forms.ColumnHeader columnHeader4; 
     private System.Windows.Forms.ColumnHeader columnHeader5; 
     private System.Windows.Forms.ColumnHeader columnHeader6; 
    } 
} 
+0

У вас установлены последние графические драйверы для вашей карты? –

+0

Установлены последние графические драйверы. Эта проблема может быть воспроизведена на каждой машине. – DxCK

+0

Как вы заполняете элементы в списке? Можете ли вы показать код, который вы используете, заполнить элементы списка? –

ответ

4

Я измеряю медленный собственный по этому коду, XP рисует список примерно за 47 мс, для Win7 требуется около 96 мс, что примерно в два раза медленнее. Не уверен, что это заслуживает прозвище «ад». Я не знаю, что вызывает его, но не сомневаюсь, что Aero имеет к этому какое-то отношение. Отключение это не совсем желательный вариант.

К счастью, вы сделали ошибку в своем коде, который стоит 48 мс в моих измерениях. Предоставление вам точного перфоманса на XP. Вы повторно используете тот же ListViewItem, вы должны создать новый. Добавьте эту строку кода в обработчик события RetrieveVirtualItem:

private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
    { 
     var _item = new ListViewItem(new string[6]); 
     // etc... 
    } 

И избавиться от этого поля.

+0

Пробовал этот, не вижу разницы. – DxCK

+0

Хм, это было репродуцировано как на XP, так и на Win7. Я не вижу, что вы видите, измеряет его, переопределяя WndProc() и используя секундомер, чтобы измерить время для m.Msg == 15. –

1

Попробуйте изменить SetStyle линию:

base.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 

UserPaint -

"Если это правда, контроль сам краски , а не операционная система делает так" (MSDN)

.

+0

Увидели странное поведение при использовании ControlStyles.UserPaint для владельца, нарисованного ListView. Я предлагаю использовать свойство DoubleBuffered в ListView (оно защищено, поэтому нужно наследовать, а затем установить его в конструкторе). –

0

Попробуйте использовать WS_EX_COMPOSITED, это повышает производительность виртуального списка совсем немного:

protected override CreateParams CreateParams 
{ 
    get 
    { 
     CreateParams cp = base.CreateParams; 
     cp.ExStyle |= 0x02000000; 
     return cp; 
    } 
} 

Отредактировано: По крайней мере, это уменьшает рисунок артефакты.