Отображение вкладки с большим количеством элементов управления ComboBox происходит медленно с WinForms - PullRequest
3 голосов
/ 24 февраля 2009

Я установил диалог с несколькими вкладками. Один из них содержит двадцать полей со списком, каждый из которых содержит более 100 элементов, добавленных так:

foreach (var x in collection)
{
    string text = FormatItem (x);
    combo.Items.Add (text);
}

так что ничего особенного в предметах нет. Они представляют собой простые строки, и поля со списком заполняются при создании диалога. Это происходит почти мгновенно.

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

Я загрузил символы для System.Windows.Forms и попытался взломать отладчик, пока программа зависла. Я обнаружил трассировку стека со следующими вызовами:

System.Windows.Forms.Control.CreateHandle()
System.Windows.Forms.ComboBox.CreateHandle()
System.Windows.Forms.Control.CreateControl(...) x 3
System.Windows.Forms.Control.SetVisibleCore(true)
System.Windows.Forms.TabPage.Visible.set(true)

, что приводит к множеству собственных переходов, WndProc вызовов и т. Д. Я полагаю, это происходит для каждого элемента в каждом поле со списком. Уф.

Очевидно, я не могу оптимизировать WinForms. Но, может быть, я могу предпринять некоторые действия, чтобы избежать того, чтобы весь этот ад был потерян на моем плохом графическом интерфейсе? Есть идеи?

Примечание:

  1. У меня нет комбо-обработчиков событий, которые могут быть вызваны, когда элементы управления создаются по-настоящему.

  2. Если я попытаюсь получить доступ к свойству Handle полей со списком сразу после создания и заполнения формы, я плачу штраф в этот момент, а не когда вкладка становится видимой в первый раз. Но не нужно также ждать несколько секунд при создании формы. Я действительно хочу избавиться от долгого времени наладки.

  3. Идея применения BeginUpdate и EndUpdate здесь не применима: их следует использовать для предотвращения перекрашивания элемента управления при заполнении его списка элементов. Но в моем случае проблема возникает хорошо после того, как элемент управления был настроен.

Ответы [ 5 ]

1 голос
/ 18 сентября 2012

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

Я заполнял комбо в обработчике события OnLoad формы, однако, когда я переместил этот код в конструктор, после InitializeComponent () вообще не было задержки.

Я полагаю, что выполнение этой операции в OnLoad вызывало перерисовку комбо, отсюда и задержка? В любом случае, я подумал, что добавлю это на тот случай, если это пригодится кому-то еще в этой ситуации.

1 голос
/ 26 февраля 2009

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

В конце концов я решил исправить проблему, выполнив трюк, аналогичный предложенному danbystrom , т.е. заполнить коллекцию Items можно только тогда, когда фокус впервые прибывает в комбо. Это по-прежнему приводит к заметной задержке - времени создания всех элементов (в пределах пары вызовов методов BeginUpdate и EndUpdate), но это допустимо (приблизительно 200 мс по сравнению с несколькими секундами в моем исходном сценарии).

1 голос
/ 24 февраля 2009

Вместо итерации ваших коллекций, не станет ли установка ComboBox.DataSource жизнеспособной и намного более быстрой альтернативой?

comboBox1.DataSource = myCollection1;
comboBox2.DataSource = myCollection2;
comboBox3.DataSource = myCollection3;
// and so on...

Вот более полный пример:

public class Entity
    {
        public string Title { get; set; }
        public override string ToString()
        {
            return Title;
        }
    }
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            List<Entity> list = new List<Entity>
                                    {
                                        new Entity {Title = "Item1"},
                                        new Entity {Title = "Item2"},
                                        new Entity {Title = "Item3"}
                                    };

            comboBox1.DataSource = list;

        }
1 голос
/ 24 февраля 2009

То, что вы говорите, не согласуется с тем, что я когда-либо наблюдал ...: s

Но вы пытались использовать .BeginUpdate / .EndUpdate?

Еще одна вещь, которую вы можете попробовать - , а не заполнять поля, пока не потребуется. Задерживайте его до тех пор, пока поле не будет сфокусировано, например ... (Если вы перехватываете выпадающее событие, некоторый пользователь может быть раздражен, что клавиши со стрелками вверх / вниз не будут работать.)

0 голосов
/ 25 февраля 2009

Множество элементов управления в форме может быть проблемой. Однажды у меня была форма, которая динамически создавала между 50-100 текстовыми полями. Это было медленно, чтобы загрузить.

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

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