WinForms ListView и TreeView: странные проблемы с производительностью - PullRequest
3 голосов
/ 07 февраля 2012

При оптимизации пользовательского интерфейса в нашем проекте я заметил очень странное повышение в ListView и не понял, откуда он.

Простое добавление 5000 элементов в listView (просмотр: список) - 3815 мс:

for (int i = 0; i < 5000; i++)
         listView1.Items.Add((Guid.NewGuid().ToString()));

С BeginUpdate () + EndUpdate () - 2317 мс:

listView1.BeginUpdate();
for (int i = 0; i < 5000; i++)
    listView1.Items.Add((Guid.NewGuid().ToString()));
listView1.EndUpdate();

С Hide () + Show () - 163 мс (без ошибок, более чем в 10 раз быстрее):

listView1.Hide();
for (int i = 0; i < 5000; i++)
    listView1.Items.Add((Guid.NewGuid().ToString()));
listView1.Show();

Стиль также изменился. Вместо 2 столбцов у меня теперь 4.

Почему этот путь такой быстрый? Более того, почему запуск со скрытым ListView (Visible: false) и показ его после заполнения не имеет такого же повышения производительности?

TreeView отличается. Простое добавление 5000 узлов - 2130 мс:

for (int i = 0; i < 5000; i++)
    treeView1.Nodes.Add((Guid.NewGuid().ToString()));

С Скрыть () + Показать () - 1048 мс:

treeView1.Hide();
for (int i = 0; i < 5000; i++)
    treeView1.Nodes.Add((Guid.NewGuid().ToString()));
treeView1.Show();

С BeginUpdate () + EndUpdate () - 291 мс:

treeView1.BeginUpdate();
for (int i = 0; i < 5000; i++)
    treeView1.Nodes.Add((Guid.NewGuid().ToString()));
treeView1.EndUpdate();

Ответы [ 2 ]

2 голосов
/ 09 марта 2012

Кажется, это ошибка.Когда элемент управления скрыт, он не вычисляет экстенты элементов (что-то вроде Graphics.MeasureString или его собственный эквивалент), когда они добавляются (что имеет смысл), и не вычисляет его позже, когда отображается элемент управления (что, вероятно, ошибка).По этой причине вы получаете 4 столбца вместо 2. Обратите внимание, что когда вы получаете 2 столбца, элементы не усекаются, потому что был выполнен этот расчет размера.Когда вы получаете 4 столбца, дисплей обычно некорректен.

И почему он не делает его невидимым с самого начала?Причина в том, что в этом случае дескриптор элемента управления не создается (базовый элемент управления Win32 еще не создан) до тех пор, пока вы не вызовете метод Show или не создадите что-либо, что заставляет этот дескриптор быть создан.И тогда Show впервые создаст дескриптор, выполняя много другого кода, включая OnHandleCreated, и где-то в этот момент код организует элементы и вычисляет их размеры.

Вы можете проверитьIsHandleCreated свойство равно false до первого Show вызова, если элемент управления был невидимым с самого начала.

Вы также можете явно создать дескриптор, т.е.просто пытаясь прочитать свойство Handle (это вынуждает создать дескриптор), а затем он ведет себя так же - быстро, но отображается неверное сообщение:

IntPtr handle = listView1.Handle;
for (int i = 0; i < 5000; i++)
    listView1.Items.Add((Guid.NewGuid().ToString()));
listView1.Show();

Если дескриптор былсозданный ранее, OnHandleCreated вместе с вычислением размера также вызывался, но в то время список был пустым.

0 голосов
/ 07 февраля 2012

Рекомендуется, если вы добавляете элементы без скрытия вида списка .. Рисует элемент за элементом, а когда вы скрываете вид списка, он будет рисовать все элементы одновременно ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...