下拉框中帶有複選框的OwnerDraw組合框
介紹 我需要向列表視
圖新增篩選。列表檢視已經有了一個工具條,我可以在其中新增適當的小部件。我決定使用帶有複選框的下拉組合框來開啟和關閉專案,這是最節省空間、最直觀的實現方式。但是,這需要一個所有者繪製的組合框。幸運的是,2.0版本的. net框架包含了一個助手類CheckBoxRenderer,如果提供正確的引數,它將為您將複選框呈現到下拉列表中。 使用的程式碼 第一步是子類化System.Windows.Forms。組合框類: 隱藏,複製Code
public partial class CheckComboBox : ComboBox { publicCheckComboBox() { this.DrawMode = DrawMode.OwnerDrawFixed; ... } ... }
注意,我設定了DrawMode屬性來告訴ComboBox我們打算自己呈現下拉列表項。下一步是定義一個類來包含下拉列表項資料並維護狀態。這是一個簡單的類: 隱藏,收縮,複製Code
public class CheckComboBoxItem { public CheckComboBoxItem( string text, bool initialCheckState ) { _checkState = initialCheckState; _text = text; } privatebool _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