2012-07-12 86 views
15

特定項目我有一個WinForms應用程序,我想知道是否有禁用ComboBox項不改變SelectedIndex屬性-1所有殘障值的更優雅的方式。禁用的組合框

我一直在使用Google和很多解決方案都涉及ASP.Net DropDownLists但這LINK看起來很有希望。我想我可能不得不建立自己的組合框控件,但在重新發明輪子之前,我想我會問在這裏是否有可能。

UPDATE

下面是最終的解決方案,這要歸功於阿里夫Eqbal:

//Add a Combobox to a form and name it comboBox1 
// 
    using System; 
    using System.Drawing; 
    using System.Windows.Forms; 

    namespace WindowsFormsApplication6 
    { 
     public partial class Form1 : Form 
     { 
      public Form1() 
      { 
       InitializeComponent(); 
       this.comboBox1.DrawMode = DrawMode.OwnerDrawFixed; 
       this.comboBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.comboBox1_DrawItem); 
       this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); 
      } 

      private void Form1_Load(object sender, EventArgs e) 
      { 
       this.comboBox1.Items.Add("Test1"); 
       this.comboBox1.Items.Add("Test2"); 
       this.comboBox1.Items.Add("Test3"); 
       this.comboBox1.Items.Add("Test4"); 
       this.comboBox1.Items.Add("Test5"); 
       this.comboBox1.Items.Add("Test6"); 
       this.comboBox1.Items.Add("Test7"); 
      } 

      Font myFont = new Font("Aerial", 10, FontStyle.Underline|FontStyle.Regular); 
      Font myFont2 = new Font("Aerial", 10, FontStyle.Italic|FontStyle.Strikeout); 

      private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
      { 
       if (e.Index == 1 || e.Index == 4 || e.Index == 5)//We are disabling item based on Index, you can have your logic here 
       { 
        e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont2, Brushes.LightSlateGray, e.Bounds); 
       } 
       else 
       { 
        e.DrawBackground(); 
        e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.Black, e.Bounds); 
        e.DrawFocusRectangle(); 
       } 
      } 

      void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
      { 
       if (comboBox1.SelectedIndex == 1 || comboBox1.SelectedIndex == 4 || comboBox1.SelectedIndex == 5) 
        comboBox1.SelectedIndex = -1; 
      } 
     } 
    } 
+3

ASP.NET =的WinForms,不看那裏。擴展基本ComboBox並不是非常困難(通常是爲了添加複選框或圖標或者什麼),但我不認爲有這樣的標準支持。 – 2012-07-12 04:52:38

+1

你提到的鏈接去,如果你真的想給用戶的項目的感覺被禁用的方式。您可能想要將文本繪製爲灰色,您可能不想顯示選擇背景顏色等等,當然用戶仍然可以選擇該項目,因此您當然需要處理selectedIndexChanged並將selectedIndex設置爲-1。但是這個練習在視覺上會更具啓發性。 – 2012-07-12 06:25:06

回答

23

嘗試......它是否滿足你的目的:

我假設你有一個組合框所謂ComboBox1,你想,即一個項目與索引1

設置的DrawMode屬性禁用第二項組合框OwnerDrawFixed然後處理這兩個事件,如下圖所示:

Font myFont = new Font("Aerial", 10, FontStyle.Regular); 

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
{   
    if (e.Index == 1)//We are disabling item based on Index, you can have your logic here 
    { 
     e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.LightGray, e.Bounds); 
    } 
    else 
    { 
     e.DrawBackground(); 
     e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.Black, e.Bounds); 
     e.DrawFocusRectangle(); 
    } 
} 

void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     if (comboBox1.SelectedIndex == 1) 
      comboBox1.SelectedIndex = -1; 
    } 
+2

你我的朋友是天才,謝謝! – 2012-07-12 07:09:50

11

這裏有阿里夫Eqbal的100%基於我的答案。 的改進是:

  • 重用組合框,而不是建立新的(因此,如果您在設計改變它,你不會有更新的代碼)
  • 重用默認FontSystemBrushes每次灰色項目重繪
  • 殘疾人的項目,我不得不重新繪製背景,否則,它們的顏色;(如果你手動更改,雖然組合框所使用的顏色也不會工作,所以它應該符合你的主題)越來越接近黑色
  • 創建專用IsItemDisabled米ethod避免複製/粘貼

// Don't forget to change DrawMode, else the DrawItem event won't be called. 
// this.comboBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; 

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
{ 
    ComboBox comboBox = (ComboBox)sender; 

    if (IsItemDisabled(e.Index)) 
    { 
     // NOTE we must draw the background or else each time we hover over the text it will be redrawn and its color will get darker and darker. 
     e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds); 
     e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, SystemBrushes.GrayText, e.Bounds); 
    } 
    else 
    { 
     e.DrawBackground(); 
     e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, SystemBrushes.ControlText, e.Bounds); 
     e.DrawFocusRectangle(); 
    } 
} 

void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (IsItemDisabled(comboBox1.SelectedIndex)) 
     comboBox1.SelectedIndex = -1; 
} 

bool IsItemDisabled(int index) 
{ 
    // We are disabling item based on Index, you can have your logic here 
    return index % 2 == 1; 
} 
4

這裏有一個進一步的修改。上述解決方案的問題是選定的項目不可見,因爲字體前景和背景選擇都很暗。因此,字體應根據e.State值設置:

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
    { 
     ComboBox comboBox = (ComboBox)sender; 
     if (e.Index >= 0) 
     { 
      if (IsItemDisabled(e.Index)) 
      { 
       e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds); 
       e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, Brushes.LightSlateGray, e.Bounds); 
      } 
      else 
      { 
       e.DrawBackground(); 

       // Set the brush according to whether the item is selected or not 
       Brush br = ((e.State & DrawItemState.Selected) > 0) ? SystemBrushes.HighlightText : SystemBrushes.ControlText; 

       e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, br, e.Bounds); 
       e.DrawFocusRectangle(); 
      } 
     } 
    }