一、問題的提出
在上一篇文章中我們談到了如何用編程的方式實現ComboBox美容,使普通的ComboBox控件變得多姿多彩(如字體的變大、顏色的變化以及中上圖像),但是這種變化是有一定的局限性:即強烈的順序感。本文就來解決"強烈的順序感"的問題,這種做法是很有必要的。
例如在一個ComboBox中顯示的全體2001級計算機系優秀學生干部,為了明確地區分某個學生是屬性某一個年級,我們可采用在每個學生面前放置圖標的方法,如一年級的學生面前放置 ,二年級的學生前面放置 ,三年級的學生面前放置 ,不知年級的學生前面不放置任何圖標等來區分,如圖1所示。
圖1
在圖1中可以看出"沒有強烈的順序感",彌補了上一篇文章的不足之處。這到底是如何實現的呢?
二、解決方法分析
從圖1可以看出,我們所用的組合框只是在標准組合框的基礎上進行了修改(添加圖像列表)而形成的,因此讀者很容易想到C#中自定義控件的方法之一:繼承原有控件的方法。本文中的"變形組合框"就是在標准的ComboBox繼承得到的,在標准的ComboBox基礎上添加了一個圖像列表,其代碼如下:
public class imageComboBox : System.Windows.Forms.ComboBox//繼承ComboBox { //添加ImageList型的變量來保存ImageList屬性的值 private ImageList _imageList; //定義ImageList屬性 public ImageList ImageList { get { return _imageList; } set { _imageList = value; } } /*設置繪畫方式為OwnerDrawFixed,這一步很關鍵*/ public imageComboBox() { DrawMode = DrawMode.OwnerDrawFixed; } //重載OnDrawItem函數,來繪制組合框中每一列表項 protected override void OnDrawItem(DrawItemEventArgs ea) { ea.DrawBackground(); ea.DrawFocusRectangle(); imageComboBoxItem item; Size imageSize = _imageList.ImageSize; Rectangle bounds = ea.Bounds; try { /*關於imageComboBoxItem的定義在下面論述*,這一步也是關鍵/ item = (imageComboBoxItem)Items[ea.Index]; /*在此處用了一個小技巧。因為組合框列表項中的索引從0開始,對於那些沒有圖標的項(用於不知道屬性哪一個年級的學生)把其索引設置為-1,即只要其索引值不為-1,表明有圖像;否則沒有圖像*/ if (item.ImageIndex != -1)//即有圖像又有文本 { //畫圖像 _imageList.Draw(ea.Graphics, bounds.Left, bounds.Top, item.ImageIndex); //繪制文本 ea.Graphics.DrawString(item.Text, ea.Font, new SolidBrush(ea.ForeColor), bounds.Left+imageSize.Width, bounds.Top); } else//只有文本,沒有圖像 { //寫文本 ea.Graphics.DrawString(item.Text, ea.Font, new SolidBrush(ea.ForeColor), bounds.Left, bounds.Top); } } //一定要有 catch { if (ea.Index != -1) { ea.Graphics.DrawString(Items[ea.Index].ToString(), ea.Font, new SolidBrush(ea.ForeColor), bounds.Left, bounds.Top); } else { ea.Graphics.DrawString(Text, ea.Font, new SolidBrush(ea.ForeColor), bounds.Left, bounds.Top); } } base.OnDrawItem(ea); } }
再仔細觀察圖1,發現"變形"組合框中列表項與普通組合框中列表項中有所不同(多了圖像),在此我們定義一個類來描述"變形"組合框列表項,其代碼如下:
//"變形"組合框列表項類 public class imageComboBoxItem { //定義文本屬性 private string _text; public string Text { get {return _text;} set {_text = value;} } //定義圖象索引屬性 private int _imageIndex; public int ImageIndex { get {return _imageIndex;} set {_imageIndex = value;} } //初始化函數之一:即沒有圖象也沒有文本 public imageComboBoxItem():this("",-1) { } //初始化函數之二:沒有圖象,只有文本(針對不知屬性哪一年級學生) public imageComboBoxItem(string text): this(text, -1) { } //初始化函數之三:文本與圖象都有 public imageComboBoxItem(string text, int imageIndex) { _text = text; _imageIndex = imageIndex; } public override string ToString() { return _text; } }