禁用组合框中的特定项目

时间:2012-07-12 04:44:01

标签: c# winforms combobox

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

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

更新

这是最终解决方案,感谢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;
            }
        }
    }

3 个答案:

答案 0 :(得分:26)

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

我假设您有一个名为ComboBox1的组合框,并且您想禁用第二项,即索引为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;
    }

答案 1 :(得分:13)

这里的答案基于Arif Eqbal的100%。 改进是:

  • 重用ComboBox中的Font而不是创建新的SystemBrushes(因此,如果您在设计器中更改它,则无法更新代码)
  • 重复使用默认IsItemDisabled(因此它应与您的主题相匹配;如果您手动更改ComboBox中使用的颜色,它将无法正常工作)
  • 对于禁用的项目我必须重绘背景,否则每次重绘灰色项目时,它们的颜色越来越接近黑色
  • 创建专用的// 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; } 方法以避免复制/粘贴

{{1}}

答案 2 :(得分:4)

这是进一步的修改。上述解决方案的问题在于所选项目不可见,因为字体前景和背景选择都是暗的。因此,应根据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();
            }
        }
    }