С# Combobox не отображает элементы

Я пытаюсь заполнить поле со списком на С#, но по какой-то причине элементы не отображаются.

public List<string> items
{
    set
    {
        combobox.Items.Clear();
        foreach(string s in value)
        {
            combobox.Items.Add(s);
        }
        combobox.Update();
    }
}

Это кажется невероятно простым кодом. Я просто не вижу, что не так. Вызывается так:

private void StoreNames(List<string> names)
{
    if (selectionForm.InvokeRequired)
        selectionForm.Invoke((MethodInvoker)delegate { selectionForm.items = names; });
    else
        selectionForm.items = names;
}

Интересно, что это работает, когда InvokeRequired возвращает true, но не работает, когда возвращает false.

РЕДАКТИРОВАТЬ: я обнаружил, что selectionForm.IsHandleCreated в настоящее время false. Это приводит к тому, что InvokeRequired возвращает false, но также и поэтому регулярный вызов сеттера не работает. Я понятия не имею, почему IsHandleCreated имеет значение false. Форма была Show()n.


person Daniel    schedule 02.08.2011    source источник
comment
Какой поток устанавливает свойство? Это поток таймера или основной цикл сообщений Windows?   -  person agent-j    schedule 03.08.2011
comment
Я думаю, вам нужно будет добавить больше информации, чтобы получить хороший ответ.   -  person hspain    schedule 03.08.2011
comment
как вы это называете? И почему вы заполняете поле со списком сеттером?   -  person Bastardo    schedule 03.08.2011
comment
Просто примечание: вам, вероятно, не следует возиться с Invalidate/Update/Refresh в этом контексте. Просто позвольте Items.Add сделать это за вас.   -  person Brian Gordon    schedule 03.08.2011
comment
Хорошо, сейчас добавлю контекст.   -  person Daniel    schedule 03.08.2011
comment
Кроме того, это не работало, когда у меня не было обновления, поэтому я добавил его, и оно все еще не работает.   -  person Daniel    schedule 03.08.2011
comment
Куда вы звоните StoreNames и как? Пожалуйста, используйте @ при ответе, чтобы мы получили уведомление, например. @Shadow сообщит мне, что вы ответили, чтобы я мог увидеть это и помочь в дальнейшем.   -  person Shadow Wizard Wearing Mask V2    schedule 03.08.2011
comment
@shadow StoreNames вызывается асинхронно. Однако вызов поступил после того, как я позвонил selectionForm.Show().   -  person Daniel    schedule 03.08.2011
comment
@Daniel звучит как состояние гонки для меня. (сопротивляясь желанию пошутить об асинхронных процессах)   -  person David Hall    schedule 03.08.2011
comment
@Shadow Я пытался вставить while(!selectionForm.IsHandleCreated) Thread.Sleep(100); в начало StoreNames. Просто застрял в бесконечном цикле.   -  person Daniel    schedule 03.08.2011
comment
@Daniel, вам нужно показать нам код, в котором вы устанавливаете этот список. делать такие вещи, как этот цикл, чтобы попытаться решить эту проблему, - плохая идея. Вместо этого сосредоточьтесь на поиске правильного места для установки данных поля со списком.   -  person David Hall    schedule 03.08.2011
comment
@David, у меня нет доступа к коду, который устанавливает этот список; однако он определенно содержит строки, которые мне нужны.   -  person Daniel    schedule 03.08.2011


Ответы (4)


Не уверен, почему ваш код не работает - я попробовал, и он работает нормально.

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

public void StoreNames(List<string> input)
{
    if (comboBox1.InvokeRequired)
        comboBox1.Invoke((MethodInvoker)delegate {
            StoreNames(input);
        });
    else
    {
        comboBox1.Items.Clear();
        comboBox1.Items.AddRange(input.ToArray());
    }
}

Здесь мы просто передаем список прямо в метод items.AddRange() в поле со списком.

Я подозреваю, что это не сработает для вас - происходит что-то еще, но я пробовал это как из фонового рабочего (где InvokeRequired имеет значение true), так и из основного потока пользовательского интерфейса.

person David Hall    schedule 02.08.2011
comment
Я согласен, я не думаю, что проблема в Add. Я предоставил некоторую дополнительную информацию в вопросе, который, надеюсь, может помочь указать, в чем проблема. - person Daniel; 03.08.2011
comment
@Daniel - где вы вызываете код, чтобы установить свой список? Похоже, вы делаете это до того, как окно формы (следовательно, дескриптор) было фактически установлено. Возможно, попробуйте поместить код в событие загрузки формы или, если вы пытаетесь использовать какой-то шаблон ModelViewPresenter, где ведущий устанавливает эти данные, будьте очень осторожны, чтобы форма была инициализирована - возможно, путем передачи обратного вызова от докладчика к представлению. - person David Hall; 03.08.2011

Это опечатка, что вы ссылаетесь как на поле со списком, так и на поле со списком1? Возможно, это ваша ошибка.

person Jon Martin    schedule 02.08.2011

Вы имеете в виду «не отображаться», поскольку вы можете видеть их, когда отображается список, или вы даже не можете прокручивать их?

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

person SeaDrive    schedule 02.08.2011
comment
Я не могу их увидеть, прокрутить до них, ничего. MaxDropDownItems не может быть проблемой, потому что я не вижу даже 1 элемент. - person Daniel; 03.08.2011
comment
Combobox.Items.Count равно 1, а MaxDropDownItems равно 8. Выпадающее меню пусто. - person Daniel; 03.08.2011

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

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

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

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

Взгляните на этот пост от Джон Скит здесь, где он обсуждает, как правильно дождаться установки переменной другим потоком. Вы должны быть осторожны при этом - проблемы с потоками могут быть неприятными.

person David Hall    schedule 03.08.2011
comment
У меня сейчас немного времени, иначе я бы тоже предоставил код - оставьте комментарий, если вам нужны примеры чего-либо, и я посмотрю, как вернуться к нему. - person David Hall; 04.08.2011
comment
Большое спасибо за это. Я на самом деле понял, в чем проблема. Мой проект включает в себя связь с внешним устройством, и у меня есть одноэлементный класс, который обрабатывает связь. Один из его методов был delegated для метода в моей форме, и когда я уничтожил форму, я забыл -= делегат. Я был так озадачен тем, почему это всегда срабатывало в первый раз, но не во второй раз! - person Daniel; 04.08.2011