Как показать текст в выпадающем списке, когда ни один элемент не выбран? - PullRequest
21 голосов
/ 09 ноября 2011

C # & .Net 2.0 вопрос (WinForms)

У меня есть набор предметов в ComboBox, и ни один из них не выбран. Я хотел бы показать строку в комбо " Пожалуйста, выберите пункт " в этой ситуации.

Текущая реализация просто добавляет пустой элемент с таким текстом в индекс 0 и удаляет его, когда пользователь выбирает один из следующих элементов. К сожалению, пустой элемент также отображается в выпадающем списке. Как избежать этой ситуации или другим способом - есть ли способ отобразить пользовательский текст на ComboBox, когда ни один элемент не выбран?

Ответы ниже работают, когда ComboBoxStyle установлен на DropDown (ComboBox редактируемый). Есть ли возможность сделать это, когда ComboBoxStyle установлен на DropDownList?

Ответы [ 16 ]

14 голосов
/ 09 ноября 2011

Используйте метод вставки комбинированного списка, чтобы вставить «Пожалуйста, выберите элемент» в индекс 0,

comboBox1.Items.Insert(0, "Please select any value");

и добавьте все элементы в выпадающий список после первого индекса. В форме загрузки указан

comboBox1.SelectedIndex = 0;

EDIT:

При загрузке формы напишите текст в comboBox1.Text путем жесткого кодирования

comboBox1.Text = "Please, select any value";

и в событии TextChanged comboBox1 напишите следующий код

 private void comboBox1_TextChanged(object sender, EventArgs e)
        {
            if (comboBox1.SelectedIndex < 0)
            {
                comboBox1.Text = "Please, select any value";
            }
            else
            {
                comboBox1.Text = comboBox1.SelectedText;
            }
        }
5 голосов
/ 06 января 2014

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

<ComboBox SelectedIndex="0">
    <ComboBoxItem Visibility="Collapsed">Please select one...</ComboBoxItem>
    <ComboBoxItem>1</ComboBoxItem>
    <ComboBoxItem>2</ComboBoxItem>
    <ComboBoxItem>3</ComboBoxItem>
    <ComboBoxItem>4</ComboBoxItem>
</ComboBox>

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

4 голосов
/ 09 ноября 2011
    private void comboBox1_TextChanged(object sender, EventArgs e)
    {
        if (comboBox1.Text == "")
            comboBox1.Text = "Select one of the answers"; 
    }

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

2 голосов
/ 02 мая 2016

Я быстро поработал, чтобы сохранить стиль DropDownList.

class DummyComboBoxItem
{
    public string DisplayName
    {
        get
        {
            return "Make a selection ...";
        }
    }
}
public partial class mainForm : Form
{
    private DummyComboBoxItem placeholder = new DummyComboBoxItem();
    public mainForm()
    {
        InitializeComponent();

        myComboBox.DisplayMember = "DisplayName";            
        myComboBox.Items.Add(placeholder);
        foreach(object o in Objects)
        {
            myComboBox.Items.Add(o);
        }
        myComboBox.SelectedItem = placeholder;
    }

    private void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (myComboBox.SelectedItem == null) return;
        if (myComboBox.SelectedItem == placeholder) return;            
        /*
            do your stuff
        */
        myComboBox.Items.Add(placeholder);
        myComboBox.SelectedItem = placeholder;
    }

    private void myComboBox_DropDown(object sender, EventArgs e)
    {
        myComboBox.Items.Remove(placeholder);
    }

    private void myComboBox_Leave(object sender, EventArgs e)
    {
        //this covers user aborting the selection (by clicking away or choosing the system null drop down option)
        //The control may not immedietly change, but if the user clicks anywhere else it will reset
        if(myComboBox.SelectedItem != placeholder)
        {
            if(!myComboBox.Items.Contains(placeholder)) myComboBox.Items.Add(placeholder);
            myComboBox.SelectedItem = placeholder;
        }            
    }       
}

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

2 голосов
/ 09 ноября 2011

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

Вы должны быть в состоянии отправить его CB_GETCOMBOBOXINFOсообщение со структурой COMBOBOXINFO, которая будет содержать дескриптор внутреннего элемента редактирования.Затем вы можете отправить элемент управления редактирования сообщением EM_SETCUEBANNER с указателем на строку.(Обратите внимание, что для этого требуется по крайней мере XP и визуальные стили.

1 голос
/ 29 декабря 2016

Одна строка после формы InitializeComponent();

cbo_MyDropBox.Text = "Select a server...";

Тебе это нужно только один раз, верно? Все, что вам нужно сделать, если выбор является обязательным, это проверить, если индекс коробки != -1. Может кто-нибудь уточнить, почему другие ответы прыгают через обручи, чтобы это пошло?

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

1 голос
/ 09 ноября 2011

Установите для свойства Dropdownstyle поля со списком значение Dropdown и установите для текста поля со списком значение "Выбрать", как показано ниже

            combobox.DataSource = dsIn.Tables[0];
            combobox.DisplayMember = "Name";
            combobox.ValueMember = "Value";
            combobox.Text = "--Select--";
0 голосов
/ 06 февраля 2019

Я не смог получить подход @Andrei Karcheuski к работе, но он вдохновил меня на этот подход: (Я добавил свойство Localizable, чтобы подсказка могла переводиться через файлы .resx для каждого диалога, на котором вы его используете)

 public partial class HintComboBox : ComboBox
{
    string hint;
    Font greyFont;

    [Localizable(true)]
    public string Hint
    {
        get { return hint; }
        set { hint = value; Invalidate(); }
    }

    public HintComboBox()
    {
        InitializeComponent();
    }

    protected override void OnCreateControl()
    {
        base.OnCreateControl();

        if (string.IsNullOrEmpty(Text))
        {
            this.ForeColor = SystemColors.GrayText;
            Text = Hint;
        }
        else
        {
            this.ForeColor = Color.Black;
        }
    }

    private void HintComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        if( string.IsNullOrEmpty(Text) )
        {
            this.ForeColor = SystemColors.GrayText;
            Text = Hint;
        }
        else
        {
            this.ForeColor = Color.Black;
        }
    }
0 голосов
/ 22 января 2019

Это работает со стилем DropDownList - создайте класс, производный от ComboBox
(появится в Toolbox после перестроения), который рисует подсказку с помощью System.Drawing,
поместите этот элемент управления из Toolbox в вашу форму и установите подсказку "Пожалуйста, выберите пункт "в его свойствах.

public class HintComboBox : ComboBox
{
    string hint;
    public string Hint
    {
        get { return hint; }
        set { hint = value; Invalidate(); }
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == 0xf && !Focused && string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Hint))
           using (var g = CreateGraphics())
           {
               TextRenderer.DrawText(g, Hint, Font, ClientRectangle, SystemColors.GrayText, BackColor,
                                    TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter);
           }
    }
}
0 голосов
/ 09 сентября 2017

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

Я использовал комбинированный список с выпадающим стилем DropDownList, но это должно работать с другими стилями. В моем случае я хотел, чтобы текст читал «Выбрать источник», и я хотел, чтобы другие параметры были «Файл» и «Папка»

comboBox1.Items.AddRange(new string[] {"Select Source", "File", "Folder" });
comboBox1.Text = "Select Source";

Вместо этого вы можете выбрать индекс 0, если хотите. Затем я удалил элемент «Выбрать источник» при изменении индекса, поскольку больше не имеет значения, виден ли этот текст.

comboBox1.SelectedIndexChanged += new EventHandler(comboBox1_IndexChanged);

private void comboBox1_IndexChanged(object sender, EventArgs e)
    {
        comboBox1.Items.Remove("Select Source");
        if (comboBox1.SelectedIndex != -1)
        {
            if (comboBox1.SelectedIndex == 0) // File
            {
                // Do things
            }
            else if (comboBox1.SelectedIndex == 1) // Folder
            {
                // Do things
            }
        }
    }

Спасибо

...