C# 如何防止在选择项目时关闭组合框

C# 如何防止在选择项目时关闭组合框,c#,winforms,C#,Winforms,我有一个如下所示的组合框,希望在单击标题部分时阻止它关闭(例如,Administrators) 我只是尝试了以下代码 private void cmboName_SelectedIndexChanged(object sender, EventArgs e) { if (cmboName.SelectedIndex == 1) { cmboName.DroppedDown = true; return;

我有一个如下所示的组合框,希望在单击标题部分时阻止它关闭(例如,Administrators

我只是尝试了以下代码

private void cmboName_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (cmboName.SelectedIndex == 1)
        {
            cmboName.DroppedDown = true;
            return;
        }
    }

但是有一种颤抖发生了;第一个组合框将关闭,然后打开。

更新

您需要做的是抑制消息,该消息告诉系统,
组合框
希望在不应该关闭下拉列表时关闭下拉列表

为此,您需要创建一个子类:

public partial class myComboBox : ComboBox
{
    public myComboBox()
    {
        InitializeComponent();
    }

    private int direction = 0;  // where to jump when when doing keyboard selection
    private int lastIndex = -1;

    private void skip()
    {
        if (direction > 0 && (SelectedIndex + 1 < Items.Count))
            SelectedIndex += 1;
        else if (direction < 0 && (SelectedIndex - 1 >= 0))
            SelectedIndex -= 1;
        else SelectedIndex = lastIndex;

    }

    // optional, but you are owner-drawing anyway..
    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    // use your own logic to determine which entries can be selected!
    bool Invalid(int index)
    {
        return index < 0 ? true 
                         : (Items[index].ToString().StartsWith("X"));
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Up) direction = -1;
        else if (e.KeyCode == Keys.Down) direction = 1;
        else direction = 0;
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x111) /*  WM_COMMAND */
        {
            if (((int)m.WParam >> 16) == 1)
            {
                if (Invalid(SelectedIndex))
                {
                    while (Invalid(SelectedIndex)) skip();  // skip invalid entries
                    m.Result = new IntPtr(1); // return success
                    return;                   // consume the message
                }
                lastIndex = SelectedIndex;
            }
        }
        base.WndProc(ref m);
    }

  }
}
public部分类myComboBox:ComboBox
{
公共邮箱()
{
初始化组件();
}
private int direction=0;//选择键盘时跳转到哪里
private int lastIndex=-1;
私有void skip()
{
如果(方向>0&(选择的索引+1<项目数))
选择的索引+=1;
否则如果(方向<0&(选择的索引-1>=0))
选择的索引-=1;
else SelectedIndex=最后一个索引;
}
//可选,但您仍然是图纸的所有者。。
受保护的覆盖无效OnPaint(PaintEventArgs pe)
{
基础漆(pe);
}
//使用您自己的逻辑来确定可以选择哪些条目!
bool无效(整数索引)
{
返回指数<0?为真
:(Items[index].ToString().StartsWith(“X”);
}
受保护的覆盖无效OnKeyDown(KeyEventArgs e)
{
如果(e.KeyCode==Keys.Up)方向=-1;
如果(e.KeyCode==Keys.Down)方向=1,则为else;
else方向=0;
}
受保护的覆盖无效WndProc(参考消息m)
{
如果(m.Msg==0x111)/*WM_命令*/
{
if(((int)m.WParam>>16)==1)
{
如果(无效(已选择索引))
{
while(Invalid(SelectedIndex))skip();//跳过无效条目
m、 Result=newintptr(1);//返回成功
return;//使用消息
}
lastIndex=选定的索引;
}
}
基准WndProc(参考m);
}
}
}

注意,我的测试使用一个简单的检查来检查无效/不可选择的分组/标题项。您需要使用自己的适当检查,而不是检查内容是否为“X”!可能与您在
ItemDraw
事件中粗体显示这些项目时使用的条件相同。

更新

您需要做的是抑制消息,该消息告诉系统,
组合框
希望在不应该关闭下拉列表时关闭下拉列表

为此,您需要创建一个子类:

public partial class myComboBox : ComboBox
{
    public myComboBox()
    {
        InitializeComponent();
    }

    private int direction = 0;  // where to jump when when doing keyboard selection
    private int lastIndex = -1;

    private void skip()
    {
        if (direction > 0 && (SelectedIndex + 1 < Items.Count))
            SelectedIndex += 1;
        else if (direction < 0 && (SelectedIndex - 1 >= 0))
            SelectedIndex -= 1;
        else SelectedIndex = lastIndex;

    }

    // optional, but you are owner-drawing anyway..
    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    // use your own logic to determine which entries can be selected!
    bool Invalid(int index)
    {
        return index < 0 ? true 
                         : (Items[index].ToString().StartsWith("X"));
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Up) direction = -1;
        else if (e.KeyCode == Keys.Down) direction = 1;
        else direction = 0;
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x111) /*  WM_COMMAND */
        {
            if (((int)m.WParam >> 16) == 1)
            {
                if (Invalid(SelectedIndex))
                {
                    while (Invalid(SelectedIndex)) skip();  // skip invalid entries
                    m.Result = new IntPtr(1); // return success
                    return;                   // consume the message
                }
                lastIndex = SelectedIndex;
            }
        }
        base.WndProc(ref m);
    }

  }
}
public部分类myComboBox:ComboBox
{
公共邮箱()
{
初始化组件();
}
private int direction=0;//选择键盘时跳转到哪里
private int lastIndex=-1;
私有void skip()
{
如果(方向>0&(选择的索引+1<项目数))
选择的索引+=1;
否则如果(方向<0&(选择的索引-1>=0))
选择的索引-=1;
else SelectedIndex=最后一个索引;
}
//可选,但您仍然是图纸的所有者。。
受保护的覆盖无效OnPaint(PaintEventArgs pe)
{
基础漆(pe);
}
//使用您自己的逻辑来确定可以选择哪些条目!
bool无效(整数索引)
{
返回指数<0?为真
:(Items[index].ToString().StartsWith(“X”);
}
受保护的覆盖无效OnKeyDown(KeyEventArgs e)
{
如果(e.KeyCode==Keys.Up)方向=-1;
如果(e.KeyCode==Keys.Down)方向=1,则为else;
else方向=0;
}
受保护的覆盖无效WndProc(参考消息m)
{
如果(m.Msg==0x111)/*WM_命令*/
{
if(((int)m.WParam>>16)==1)
{
如果(无效(已选择索引))
{
while(Invalid(SelectedIndex))skip();//跳过无效条目
m、 Result=newintptr(1);//返回成功
return;//使用消息
}
lastIndex=选定的索引;
}
}
基准WndProc(参考m);
}
}
}

注意,我的测试使用一个简单的检查来检查无效/不可选择的分组/标题项。您需要使用自己的适当检查,而不是检查内容是否为“X”!可能与您在
ItemDraw
事件中粗体显示这些项目时使用的条件相同。

一种解决方案是从选择中禁用某些项目。
试试这个:

private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
        }

 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            string itemText = comboBox1.GetItemText(comboBox1.SelectedItem);

            if ((itemText == "Admins") || (itemText == "Users"))            
                comboBox1.SelectedIndex = -1;
        }

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            string itemText = comboBox1.GetItemText(comboBox1.Items[e.Index]);

            if ((itemText == "Admins") || (itemText == "Users"))
            {
                using (var f = new Font("Microsoft Sans Serif", 8, FontStyle.Bold))
                    e.Graphics.DrawString(itemText, f, Brushes.Black, e.Bounds);
            }
            else
            {
                e.DrawBackground();

                using (var f = new Font("Microsoft Sans Serif", 8, FontStyle.Regular))
                    e.Graphics.DrawString(itemText, f, Brushes.Black, e.Bounds);

                e.DrawFocusRectangle();
            }
        }

这不是你想要的,但它是下一个最好的选择。

一个解决方案是禁止选择某些项目。
试试这个:

private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
        }

 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            string itemText = comboBox1.GetItemText(comboBox1.SelectedItem);

            if ((itemText == "Admins") || (itemText == "Users"))            
                comboBox1.SelectedIndex = -1;
        }

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            string itemText = comboBox1.GetItemText(comboBox1.Items[e.Index]);

            if ((itemText == "Admins") || (itemText == "Users"))
            {
                using (var f = new Font("Microsoft Sans Serif", 8, FontStyle.Bold))
                    e.Graphics.DrawString(itemText, f, Brushes.Black, e.Bounds);
            }
            else
            {
                e.DrawBackground();

                using (var f = new Font("Microsoft Sans Serif", 8, FontStyle.Regular))
                    e.Graphics.DrawString(itemText, f, Brushes.Black, e.Bounds);

                e.DrawFocusRectangle();
            }
        }

这不是你想要的,但它是下一个最好的东西。

你使用的是什么UI框架?WinForms或WPF?使用附加信息更新问题,而不仅仅是将其添加到注释中。您为什么希望在选择项目后阻止其关闭?这似乎是一个糟糕的UI设计好的设计应该是跳过分组项,因为我对标题部分什么都不做。它仅用于对字段进行分类。单击标题部分时,我不想关闭下拉列表。您使用的是什么UI框架?WinForms或WPF?使用附加信息更新问题,而不仅仅是将其添加到注释中。您为什么希望在选择项目后阻止其关闭?这似乎是一个糟糕的UI设计好的设计应该是跳过分组项,因为我对标题部分什么都不做。它仅用于对字段进行分类。单击标题部分时,我不想关闭下拉列表。选择更改事件中的代码与我的代码中的代码相同。是否有可能在没有任何干扰的情况下维持列表视图?这就是我在最后一句话中的意思。I h