禁用combobox中的特定项目

我有一个WinForms应用程序,我想知道是否有更优雅的方法来禁用Combobox项目而不更改所有禁用值的SelectedIndex属性-1。

我一直在谷歌搜索,很多解决方案涉及ASP.Net DropDownLists但这个LINK看起来很有希望。 我想我可能要建立自己的ComboBox控件,但在我重新发明轮子之前,我想我会问这里是否有可能。

UPDATE

这是最终解决方案,感谢Arif Eqbal:

//Add a Combobox to a form and name it comboBox1 // using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApplication6 { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.comboBox1.DrawMode = DrawMode.OwnerDrawFixed; this.comboBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.comboBox1_DrawItem); this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); } private void Form1_Load(object sender, EventArgs e) { this.comboBox1.Items.Add("Test1"); this.comboBox1.Items.Add("Test2"); this.comboBox1.Items.Add("Test3"); this.comboBox1.Items.Add("Test4"); this.comboBox1.Items.Add("Test5"); this.comboBox1.Items.Add("Test6"); this.comboBox1.Items.Add("Test7"); } Font myFont = new Font("Aerial", 10, FontStyle.Underline|FontStyle.Regular); Font myFont2 = new Font("Aerial", 10, FontStyle.Italic|FontStyle.Strikeout); private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) { if (e.Index == 1 || e.Index == 4 || e.Index == 5)//We are disabling item based on Index, you can have your logic here { e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont2, Brushes.LightSlateGray, e.Bounds); } else { e.DrawBackground(); e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.Black, e.Bounds); e.DrawFocusRectangle(); } } void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.SelectedIndex == 1 || comboBox1.SelectedIndex == 4 || comboBox1.SelectedIndex == 5) comboBox1.SelectedIndex = -1; } } } 

试试这个…它是否符合你的目的:

我假设你有一个名为ComboBox1的combobox,你想要禁用第二个项目,即索引为1的项目。

将comboBox的DrawMode属性设置为OwnerDrawFixed,然后处理这两个事件,如下所示:

 Font myFont = new Font("Aerial", 10, FontStyle.Regular); private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) { if (e.Index == 1)//We are disabling item based on Index, you can have your logic here { e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.LightGray, e.Bounds); } else { e.DrawBackground(); e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.Black, e.Bounds); e.DrawFocusRectangle(); } } void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.SelectedIndex == 1) comboBox1.SelectedIndex = -1; } 

这是我对Arif Eqbal的100%回答。 改进是:

  • 重用ComboBox中的Font而不是创建新的Font (如果在设计器中更改它,则不必更新代码)
  • 重用默认的SystemBrushes (所以它应该匹配你的主题;如果手动更改ComboBox中使用的颜色,它将无法工作)
  • 对于残疾人物品我不得不重绘背景,否则每次重绘灰色项目时,他们的颜色越来越接近黑色
  • 创建一个专用的IsItemDisabled方法来避免复制/粘贴

 // Don't forget to change DrawMode, else the DrawItem event won't be called. // this.comboBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) { ComboBox comboBox = (ComboBox)sender; if (IsItemDisabled(e.Index)) { // NOTE we must draw the background or else each time we hover over the text it will be redrawn and its color will get darker and darker. e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds); e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, SystemBrushes.GrayText, e.Bounds); } else { e.DrawBackground(); // Using winwaed's advice for selected items: // Set the brush according to whether the item is selected or not Brush brush = ( (e.State & DrawItemState.Selected) > 0) ? SystemBrushes.HighlightText : SystemBrushes.ControlText; e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, brush, e.Bounds); e.DrawFocusRectangle(); } } void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (IsItemDisabled(comboBox1.SelectedIndex)) comboBox1.SelectedIndex = -1; } bool IsItemDisabled(int index) { // We are disabling item based on Index, you can have your logic here return index % 2 == 1; } 

这是一个进一步的修改。 上述解决方案的问题在于所选项目不可见,因为字体前景和背景选择都是暗的。 因此,字体应根据e.State的值e.State

  private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) { ComboBox comboBox = (ComboBox)sender; if (e.Index >= 0) { if (IsItemDisabled(e.Index)) { e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds); e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, Brushes.LightSlateGray, e.Bounds); } else { e.DrawBackground(); // Set the brush according to whether the item is selected or not Brush br = ( (e.State & DrawItemState.Selected) > 0) ? SystemBrushes.HighlightText : SystemBrushes.ControlText; e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, br, e.Bounds); e.DrawFocusRectangle(); } } }