1. 程式人生 > 實用技巧 >下拉框中帶有複選框的OwnerDraw組合框

下拉框中帶有複選框的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