C# 当没有选择任何项目时,如何在组合框中显示文本?

C# 当没有选择任何项目时,如何在组合框中显示文本?,c#,winforms,.net-2.0,C#,Winforms,.net 2.0,C#和.Net 2.0问题(WinForms) 我在组合框中选择了一组项目,但未选择其中任何一项。在这种情况下,我想在组合框“请选择项目”上显示一个字符串 当前实现只是添加了索引0上带有此类文本的空项,并在用户选择以下项之一时将其删除。不幸的是,下拉列表中也显示了空项。如何避免这种情况或以其他方式-当未选择任何项目时,是否有任何方式在组合框上显示自定义文本 当组合框样式设置为下拉列表(组合框可编辑)时,下面的答案有效。当ComboBoxStyle设置为DropDownList时,是否有可能执行此

C#和.Net 2.0问题(WinForms)

我在组合框中选择了一组项目,但未选择其中任何一项。在这种情况下,我想在组合框“请选择项目”上显示一个字符串

当前实现只是添加了索引0上带有此类文本的空项,并在用户选择以下项之一时将其删除。不幸的是,下拉列表中也显示了空项。如何避免这种情况或以其他方式-当未选择任何项目时,是否有任何方式在组合框上显示自定义文本


组合框样式
设置为
下拉列表
组合框
可编辑)时,下面的答案有效。当
ComboBoxStyle
设置为
DropDownList
时,是否有可能执行此操作?

使用组合框的插入方法将“请选择项”插入到0索引中

comboBox1.Items.Insert(0, "Please select any value");
并将所有项目添加到第一个索引后的组合框中。以加载集的形式

comboBox1.SelectedIndex = 0;
编辑:

在表单加载中,通过硬编码将文本写入
组合框1.text

comboBox1.Text = "Please, select any value";
在comboBox1的TextChanged事件中,编写以下代码

 private void comboBox1_TextChanged(object sender, EventArgs e)
        {
            if (comboBox1.SelectedIndex < 0)
            {
                comboBox1.Text = "Please, select any value";
            }
            else
            {
                comboBox1.Text = comboBox1.SelectedText;
            }
        }
private void comboBox1\u text已更改(对象发送方,事件参数e)
{
如果(comboBox1.SelectedIndex<0)
{
comboBox1.Text=“请选择任意值”;
}
其他的
{
comboBox1.Text=comboBox1.SelectedText;
}
}
我们应该这样做
启动时,该行显示,当在组合框中选择一个项目时,将显示该项目文本。删除文本时,此文本将再次出现

如果以前的解决方案都不适用于您,为什么不在combobox上添加一些验证,例如

    var orginalindex = 0;

    private void comboBox1_SelectedItemChanged(object sender, EventArgs e)
    {
        if (comboBox1.SelectedIndex == 0)
        {
            comboBox1.Text = "Select one of the answers";
            comboBox1.SelectedIndex = comboBox1.SelectedIndex;
        }
        else
        {
            orginalindex = comboBox1.SelectedIndex;
        }
    }

将组合框的Dropdownstyle属性设置为Dropdown,并将组合框文本设置为“Select”,如下所示

            combobox.DataSource = dsIn.Tables[0];
            combobox.DisplayMember = "Name";
            combobox.ValueMember = "Value";
            combobox.Text = "--Select--";

我看不到任何本机的.NET方法可以做到这一点,但如果您想用底层Win32控件弄脏您的手

您应该能够使用包含内部编辑控件句柄的
COMBOBOXINFO
结构向其发送
CB_GETCOMBOBOXINFO
消息。 然后,您可以向编辑控件发送带有字符串指针的
EM_SETCUEBANNER
消息。
(请注意,这至少需要启用XP和视觉样式。

在这里,您可以找到由pavlo_ua创建的解决方案: 及

干杯,jbk

编辑: 所以要有明确的答案,而不仅仅是链接

当组合框的样式设置为下拉菜单(且可编辑)时,可以设置组合框的文本。 当.Net版本<3.0时,没有IsReadonly属性,因此我们需要使用win api将combobox的textbox设置为只读:

private bool m_readOnly = false;
private const int EM_SETREADONLY = 0x00CF;

internal delegate bool EnumChildWindowsCallBack( IntPtr hwnd, IntPtr lParam );

[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

[ DllImport( "user32.dll" ) ]
internal static extern int EnumChildWindows( IntPtr hWndParent, EnumChildWindowsCallBack lpEnumFunc, IntPtr lParam );


private bool EnumChildWindowsCallBackFunction(IntPtr hWnd, IntPtr lparam)
{
      if( hWnd != IntPtr.Zero )
       {
              IntPtr readonlyValue = ( m_readOnly ) ? new IntPtr( 1 ) : IntPtr.Zero;
             SendMessage( hWnd, EM_SETREADONLY, readonlyValue, IntPtr.Zero );
             comboBox1.Invalidate();
             return true;
       }
       return false;
}

private void MakeComboBoxReadOnly( bool readOnly )
{
    m_readOnly = readOnly;
    EnumChildWindowsCallBack callBack = new EnumChildWindowsCallBack(this.EnumChildWindowsCallBackFunction );
    EnumChildWindows( comboBox1.Handle, callBack, IntPtr.Zero );
}

如果将
ComboBoxStyle
设置为
DropDownList
,则确保用户选择项目的最简单方法是设置
SelectedIndex=-1
,该索引将为空。我是这样做的。它可能不是最好的方法,提供的控制最少;但是,它简单快捷,我认为这样做可能是个好主意共享它,以便为其他人提供更多选项

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

请选择一个。。。
1.
2.
3.
4.
这背后的想法是,初始选择是索引0,它是折叠的,因此一旦用户选择了其他内容,就无法在选择下使用它。缺点是,您必须记住,如果要检查选定的索引,请记住索引0表示没有选择。

为什么不使用XAML

<ComboBox x:Name="myComboBoxMenu" PlaceholderText="Hello"/>


我意识到这是一个旧线程,但我只是想让其他可能搜索此问题答案的人知道,在当前版本的Visual Studio(2015)中,有一个名为“占位符文本”的属性,它与jotbek最初询问的内容相同。请使用“公共”下的“属性”框属性。

为了保持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;
        }            
    }       
}

如果使用数据绑定,则必须创建绑定类型的虚拟版本-只需确保在任何持久性逻辑之前删除它。

表单
InitializeComponent();

你只需要它一次,对吗?如果选择是强制性的,你需要做的就是检查框索引是否
!=-1
。有人能解释一下为什么其他答案会跳转来实现这一点吗


这里我唯一缺少的是将初始文本变灰。如果你真的想这样做,只需在前面使用一个标签,并在索引更改后将其关闭。

不幸的是,上述所有操作都不适用于我,因此我在comboxbox顶部添加了一个标签,上面写着“请选择”.我使用以下代码来显示和隐藏它:

  • 当我初始化组合框时,如果没有选择值,我将其置于前面并设置文本:

    PleaseSelectValueLabel.BringToFront();
    PleaseSelectValueLabel.Text = Constants.AssessmentValuePrompt;
    
  • 如果选择了一个值,我会将其发送到后面:

    PleaseSelectValueLabel.SendToBack();
    
  • 然后,根据用户是否选择了值,我使用以下事件将标签向前或向后移动:

    private void PleaseSelectValueLabel_Click(object sender, EventArgs e)
    {
        PleaseSelectValueLabel.SendToBack();
        AssessmentValue.Focus();
    }
    
    private void AssessmentValue_Click(object sender, EventArgs e)
    {
        PleaseSelectValueLabel.SendToBack();
    }
    
    //if the user hasnt selected an item, make the please select label visible again
    private void AssessmentValue_Leave(object sender, EventArgs e)
    {
        if (AssessmentValue.SelectedIndex < 0)
        {
            PleaseSelectValueLabel.BringToFront();
        }
    }
    
    private void请选择ValueLabel\u单击(对象发送方,事件参数e)
    {
    请选择ValueLabel.SendToBack();
    AssessmentValue.Focus();
    }
    私有无效评估值\u单击(对象发送者,事件参数e)
    {
    请选择ValueLabel.SendToBack();
    }
    //如果用户未选择项目,请再次显示“请选择”标签
    私有无效评估值(对象发送者,事件参数e)
    {
    如果(AssessmentValue.SelectedIndex<0)
    {
    请选择ValueLabel.BringToFront();
    }
    }
    

  • 我也希望能找到解决这个问题的方法。我知道这是一篇比较老的帖子,但我希望我的方法能为其他人简化这个问题

    我使用的是下拉样式为DropDownList的组合框,但这应该适用于其他样式。在我的例子中,我希望文本为“选择源”,其他选项为“文件”和“文件夹”

    您可以在中选择0
    PleaseSelectValueLabel.SendToBack();
    
    private void PleaseSelectValueLabel_Click(object sender, EventArgs e)
    {
        PleaseSelectValueLabel.SendToBack();
        AssessmentValue.Focus();
    }
    
    private void AssessmentValue_Click(object sender, EventArgs e)
    {
        PleaseSelectValueLabel.SendToBack();
    }
    
    //if the user hasnt selected an item, make the please select label visible again
    private void AssessmentValue_Leave(object sender, EventArgs e)
    {
        if (AssessmentValue.SelectedIndex < 0)
        {
            PleaseSelectValueLabel.BringToFront();
        }
    }
    
    comboBox1.Items.AddRange(new string[] {"Select Source", "File", "Folder" });
    comboBox1.Text = "Select Source";
    
    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
                }
            }
        }
    
     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;
            }
        }
    
    private const int CB_SETCUEBANNER = 0x1703;
    
    [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]string lParam);
    
    SendMessage(this.comboBox1.Handle, CB_SETCUEBANNER, 0, "Please select an item...");