2013-04-04 61 views
1

這只是一個調查ComboBox來源於Enum字符串值的最佳方式的一種調查。WinForms組合框DataBound到枚舉 - 格式字符串

我知道可以數據綁定一個ComboBoxEnum像這樣:

public partial class MainForm : Form 
{ 
    public MainForm() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnLoad(EventArgs e) 
    { 
     comboBoxNames.DataSource = Enum.GetValues(typeof (Names)); 
    } 
} 

public enum Names 
{ 
    JohnDoe, 
    JaneDoe, 
    JohnJackson, 
    JackJohnson 
} 

這是結果:

enter image description here

我想格式化ComboBox這樣的顯示值PascalCase字符串值之間有一個空格,同時也會通過所選項目的Enum值,我可以在switch聲明以後:

switch ((Names)comboBoxNames.SelectedItem) 
{ 
    case Names.JohnDoe: 
     // Do something John Doe-specific 
     break; 
    case Names.JaneDoe: 
     // Do something Jane Doe-specific 
     break; 
    case Names.JohnJackson: 
     // Do something John Jackson-specific 
     break; 
    case Names.JackJohnson: 
     // Do something Jack Johnson-specific 
     break; 
} 

我知道有一個ComboBox.FormatString屬性,但我不知道如何使用它來格式化Names枚舉,我想要的方式。

這可能嗎?我不希望在Enum上使用屬性,因爲使用這些屬性最終會涉及到使用反射,這看起來像是過度殺傷似乎很簡單的事情。任何幫助將非常感激。

回答

0

我已經找到了一種方法來從Enum我喜歡格式化一個ComboBox發起字符串值,而不要求ComboBox.FormatString屬性或Format事件:使用Dictionary<Enum, string>。下面的示例代碼:

public partial class MainForm : Form 
{ 
    public MainForm() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnLoad(EventArgs e) 
    { 
     comboBoxNames.DataBindToEnum(default(Names).ToDictionary()); 
    } 

    private void btnOK_Click(object sender, EventArgs e) 
    { 
     switch (((KeyValuePair<Names, string>)comboBoxNames.SelectedItem).Key) 
     { 
      case Names.JohnDoe: 
       // Do something John Doe-specific 
       MessageBox.Show(@"John Doe!"); 
       break; 
      case Names.JaneDoe: 
       // Do something Jane Doe-specific 
       MessageBox.Show(@"Jane Doe!"); 
       break; 
      case Names.JohnJackson: 
       // Do something John Jackson-specific 
       MessageBox.Show(@"John Jackson!"); 
       break; 
      case Names.JackJohnson: 
       // Do something Jack Johnson-specific 
       MessageBox.Show(@"Jack Johnson!"); 
       break; 
     } 
    } 
} 

public enum Names 
{ 
    JohnDoe, 
    JaneDoe, 
    JohnJackson, 
    JackJohnson 
} 

public static class EnumExtensions 
{ 
    public static Dictionary<T, string> ToDictionary<T>(this T enumeration) 
    { 
     if (!enumeration.GetType().IsEnum) return null; 

     var enumValues = Enum.GetValues(typeof(T)).OfType<T>().ToList(); 
     return enumValues.ToDictionary(enumValue => enumValue, enumValue => enumValue.ToString().Spaceify()); 
    } 
} 

public static class StringExtensions 
{ 
    public static string Spaceify(this string self) 
    { 
     for (var i = 1; i < self.Length - 1; i++) 
     { 
      if (char.IsLower(self[i - 1]) && char.IsUpper(self[i]) || 
       self[i - 1] != ' ' && char.IsUpper(self[i]) && char.IsLower(self[i + 1])) 
      { 
       self = self.Insert(i, " "); 
      } 
     } 
     return self; 
    } 
} 

public static class ControlExtensions 
{ 
    public static void DataBindToEnum<T>(this ListControl listControl, IDictionary<T, string> enumAsDictionary) 
    { 
     listControl.DataSource = new BindingSource(enumAsDictionary, null); 
     listControl.DisplayMember = "Value"; 
     listControl.ValueMember = "Key"; 
    } 
} 

幾件事情需要注意:

  • 而是直接設置ComboBox.DataSource作爲enum的列表,使用Dictionary<Enum, string>設置,並設置DisplayMemberValueMember相應(擴展方法DataBindToEnum
  • 目前我們不能使用enum關鍵字作爲類型限制(類似於public static Dictionary<T, string> ToDictionary<T>(this T enumeration) **where T : enum**)。這就是爲什麼在這個方法
  • Spaceify擴展方法添加空格PascalCase字符串的身體需要一個enum檢查(處理縮寫詞也一樣)
  • 「魔術師」行,我用default關鍵字在enum這樣我就可以使用了ComboBox.SelectedItem當它的工作作爲一個列表類型的對象和周圍的enum
  • 最後,「實例」調用方法的問題得到我需要將其轉換爲KeyValuePair<Enum, string>並拉出Key,我可以在我的switch聲明中使用。沒有更多的魔力!

希望這有助於!

1

這很容易,只需添加上你的組合框格式事件,使它看起來像這樣:

private void comboBoxNames_Format(object sender, ListControlConvertEventArgs e) 
{ 
    StringBuilder newText = new StringBuilder(e.Value.ToString().Length +1); 
    newText.Append(e.Value.ToString()[0]); 
    for (int i = 1; i < e.Value.ToString().Length; i++) 
    { 
     if (char.IsUpper(e.Value.ToString()[i]) && e.Value.ToString()[i - 1] != ' ') 
      newText.Append(' '); 
     newText.Append(e.Value.ToString()[i]); 
    } 
    e.Value = newText.ToString(); 
} 
+0

這確實有效,但我希望避免事件,因爲我有很多下拉菜單,而且我不喜歡用事件處理程序(個人偏好)來污染代碼隱藏。使用可從ComboBox控件直接訪問的屬性是不可能的? – 2013-04-05 06:37:05

+0

據我所知沒有可能的方式來格式化沒有事件的項目,並仍然保持枚舉值。 – 2013-04-05 07:19:55