下拉框中带有复选框的OwnerDraw组合框

 

介绍 我需要向列表视

  

 

图添加筛选。列表视图已经有了一个工具条,我可以在其中添加适当的小部件。我决定使用带有复选框的下拉组合框来打开和关闭项目,这是最节省空间、最直观的实现方式。但是,这需要一个所有者绘制的组合框。幸运的是,2.0版本的. net框架包含了一个助手类CheckBoxRenderer,如果提供正确的参数,它将为您将复选框呈现到下拉列表中。 使用的代码 第一步是子类化System.Windows.Forms。组合框类: 隐藏,复制Code

public partial class CheckComboBox : ComboBox
{
    public CheckComboBox()
    {
        this.DrawMode = DrawMode.OwnerDrawFixed;
        ...
    }

    ...
}

注意,我设置了DrawMode属性来告诉ComboBox我们打算自己呈现下拉列表项。下一步是定义一个类来包含下拉列表项数据并维护状态。这是一个简单的类: 隐藏,收缩,复制Code

public class CheckComboBoxItem
{
    public CheckComboBoxItem( string text, bool initialCheckState )
    {
        _checkState = initialCheckState;
        _text = text;
    }

    private bool _checkState = false;
    public bool CheckState
    {
        get { return _checkState; }
        set { _checkState = value; }
    }

    private string _text = "";
    public string Text
    {
        get { return _text; }
        set { _text = value; }
    }

    public override string ToString()
    {
        return "Select Options";
    }
}

然后我们连接一个委托到ComboBox的DrawItem事件: 隐藏,复制Code

this.DrawItem += new DrawItemEventHandler(CheckComboBox_DrawItem);

并实施如下: 隐藏,收缩,复制Code

void CheckComboBox_DrawItem( object sender, DrawItemEventArgs e )
{
    if (e.Index == -1)
    {
        return;
    }

    if( !( Items[ e.Index ] is CheckComboBoxItem ) )
    {
        e.Graphics.DrawString( 
            Items[ e.Index ].ToString(), 
            this.Font, 
            Brushes.Black, 
            new Point( e.Bounds.X, e.Bounds.Y ) );
        return;
    }

    CheckComboBoxItem box = (CheckComboBoxItem)Items[ e.Index ];

    CheckBoxRenderer.RenderMatchingApplicationState = true;
    CheckBoxRenderer.DrawCheckBox( 
        e.Graphics, 
        new Point( e.Bounds.X, e.Bounds.Y ), 
        e.Bounds, 
        box.Text, 
        this.Font, 
        ( e.State & DrawItemState.Focus ) == 0, 
        box.CheckState ? CheckBoxState.CheckedNormal : 
            CheckBoxState.UncheckedNormal );
}

在这个委托中,我们要做的第一件事是验证我们呈现的项是否作为CheckComboBoxItem添加。如果不是,我们将其呈现为一个简单的字符串。否则,我们将从Items集合中(使用DrawItemEventArgs)获得适当的CheckComboBoxItem。索引属性)。然后调用CheckBoxRenderer.DrawCheckBox()方法,传入我们想要呈现复选框的图形对象以及位置、大小、文本、字体、焦点和检查状态。 结果是,它将使我们的下拉列表项看起来像复选框: 接下来,我们想在选中其中一个项目时切换检查状态。我们连接另一个委托,但这次是selectedindexchangeevent 隐藏,复制Code

this.SelectedIndexChanged += 
    new EventHandler( CheckComboBox_SelectedIndexChanged );

并实施如下: 隐藏,复制Code

void CheckComboBox_SelectedIndexChanged( object sender, EventArgs e )
{
    CheckComboBoxItem item = (CheckComboBoxItem)SelectedItem;
    item.CheckState = !item.CheckState;
    ...
}

这允许我们切换下拉框中的复选框,但不允许该控件的用户知道发生了什么事情。因此,我们还添加了一个公共事件,以通知控件的用户在下拉列表中某个项的检查状态发生变化: 隐藏,复制Code

public event EventHandler CheckStateChanged;

当我们切换上面的状态时,我们触发了这个事件,所以完整的方法是这样的: 隐藏,复制Code

void CheckComboBox_SelectedIndexChanged( object sender, EventArgs e )
{
    CheckComboBoxItem item = (CheckComboBoxItem)SelectedItem;
    item.CheckState = !item.CheckState;
    if (CheckStateChanged != null)
        CheckStateChanged(item, e);
}

使用控制 要使用这个控件,你只需将它添加到你选择的容器中,然后像这样添加项目: 隐藏,复制Code

checkComboBox1.Items.Add(new CheckComboBox.CheckComboBoxItem("One", true));
checkComboBox1.Items.Add(new CheckComboBox.CheckComboBoxItem("Two", true));
checkComboBox1.Items.Add(new CheckComboBox.CheckComboBoxItem("Three", true));

要获得用户更改检查状态的通知: 隐藏,复制Code

this.checkComboBox1.CheckStateChanged += 
    new EventHandler(this.checkComboBox1_CheckStateChanged);

可以这样处理: 隐藏,复制Code

private void checkComboBox1_CheckStateChanged(object sender, EventArgs e)
{
    if (sender is CheckComboBox.CheckComboBoxItem)
    {
        CheckComboBox.CheckComboBoxItem item = 
            (CheckComboBox.CheckComboBoxItem)sender;
        ... 
    }
}

完成的示例应用程序。 下拉。 的兴趣点 有一个烦恼,我相信肯定有比我想到的更好的解决办法。我想要的文本框部分的控制,以包含固定的文本和不可编辑。因此,作为一个权宜之计,我将它初始化为字符串“Select Options”,并覆盖CheckComboBoxItem类的ToString()方法,以始终返回相同的字符串。这样,无论用户最后选择哪一项,字符串都不会改变。这并没有使它不可编辑。 如果时间允许,我想做许多补充: 正确地对齐文本对齐(需要找出如何计算复选框位图的宽度为此正确)添加“选择所有”和“选择”项分离器顶部的下拉允许其他控件类型下拉(例如-单选按钮) 历史 2007年5月24日:原版本已上载 本文转载于:http://www.diyabc.com/frontweb/news346.html

posted @ 2020-08-05 10:14  Dincat  阅读(264)  评论(0编辑  收藏  举报