Заполнение FlowLayoutPanel большим количеством элементов управления и рисование миниатюр по запросу - PullRequest
6 голосов
/ 23 января 2009

Я пытаюсь создать вид элемента управления ImageListBox, который будет отображать большое количество миниатюр, например, тот, который используется в Picasa.

Это мой дизайн:

У меня есть FlowLayoutPanel, который заполнен большим количеством UserControl объектов, например, 4000. Каждому UserControl назначается делегат на событие Paint. Когда вызывается событие Paint, оно проверяет миниатюру в кэш-памяти и, если изображение отсутствует в кэше, извлекает его с диска.

У меня есть две проблемы, которые я пытаюсь решить:

  1. Похоже, что WinForms вызовет событие Paint, даже если UserControl не отображается. Фактически видно только 10 или около того элементов управления, остальные - нет (FlowLayoutPanel.AutoScroll установлен на true). В результате он пытается получить эскизы для всех изображений, и это занимает много времени.

  2. Добавление UserControl объектов в FlowLayoutPanel занимает несколько длительное время, около 2-3 секунд. Я могу жить с этим, но мне интересно, есть ли лучший способ сделать это, чем:

    UserControl[] boxes = new UserControl[N];
    // populate array
    panel.SuspendLayout();
    panel.Controls.AddRange(boxes);
    panel.ResumeLayout();
    

Ответы [ 3 ]

5 голосов
/ 24 января 2009

Чтобы повысить скорость заполнения FlowLayoutPanel пользовательскими элементами управления, отключите обновление макета при добавлении элементов управления.

Непосредственно перед вашей петлей вызовите SuspendLayout(), а затем в конце вызова ResumeLayout(). Обязательно используйте try-finally, чтобы гарантировать выполнение ResumeLayout(), даже если возникает исключение.

3 голосов
/ 23 января 2009

Я бы не стал добавлять столько пользовательских элементов управления. Скорее, у меня будет ряд структур данных, в которых хранится информация о том, какой эскиз использовать, позиционировать и т. Д., И т. Д., А затем обрабатывать рендеринг каждого требуемого эскиза.

Конечно, вы будете рендерить только то, что вам нужно, проверив аргументы событий рисования в вашем элементе управления и отобразив миниатюры, которые отображаются и требуют рендеринга.

1 голос
/ 23 января 2009

Aha! Я что-то нашел.

Когда UserControl не отображается и получает событие Paint, тогда e.ClipRectangle.IsEmpty имеет значение true!

...