c# - 將枚舉綁定到WinForms組合框,然後進行設置





.net combobox enums (20)


基於來自@Amir Shenouda的回答,我最終得出這個結論:

Enum的定義:

public enum Status { Active = 0, Canceled = 3 }; 

從它設置下拉值:

cbStatus.DataSource = Enum.GetValues(typeof(Status));

從所選項目獲取枚舉:

Status? status = cbStatus.SelectedValue as Status?;

很多人已經回答瞭如何將枚舉綁定到WinForms中的組合框的問題。 就像這樣:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));

但是,如果不能設置顯示的實際值,那就沒用了。

我努力了:

comboBox1.SelectedItem = MyEnum.Something; // Does not work. SelectedItem remains null

我也試過:

comboBox1.SelectedIndex = Convert.ToInt32(MyEnum.Something); // ArgumentOutOfRangeException, SelectedIndex remains -1

有沒有人有任何想法如何做到這一點?




Enum

public enum Status { Active = 0, Canceled = 3 }; 

從它設置下拉值

cbStatus.DataSource = Enum.GetValues(typeof(Status));

從選定的項目獲取枚舉

Status status; 
Enum.TryParse<Status>(cbStatus.SelectedValue.ToString(), out status); 



    public enum Colors
    {
        Red = 10,
        Blue = 20,
        Green = 30,
        Yellow = 40,
    }

comboBox1.DataSource = Enum.GetValues(typeof(Colors));

完整源代碼... 將枚舉綁定到Combobox




你可以使用“FindString ..”函數:

Public Class Form1
    Public Enum Test
        pete
        jack
        fran
        bill
    End Enum
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ComboBox1.DataSource = [Enum].GetValues(GetType(Test))
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact("jack")
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact(Test.jack.ToString())
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact([Enum].GetName(GetType(Test), Test.jack))
        ComboBox1.SelectedItem = Test.bill
    End Sub
End Class



 public static void FillByEnumOrderByNumber<TEnum>(this System.Windows.Forms.ListControl ctrl, TEnum enum1, bool showValueInDisplay = true) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum enumValue in Enum.GetValues(typeof(TEnum))
                     select
                        new
                         KeyValuePair<TEnum, string>(   (enumValue), enumValue.ToString());

        ctrl.DataSource = values
            .OrderBy(x => x.Key)

            .ToList();

        ctrl.DisplayMember = "Value";
        ctrl.ValueMember = "Key";

        ctrl.SelectedValue = enum1;
    }
    public static void  FillByEnumOrderByName<TEnum>(this System.Windows.Forms.ListControl ctrl, TEnum enum1, bool showValueInDisplay = true  ) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum enumValue in Enum.GetValues(typeof(TEnum))
                     select 
                        new 
                         KeyValuePair<TEnum,string> ( (enumValue),  enumValue.ToString()  );

        ctrl.DataSource = values
            .OrderBy(x=>x.Value)
            .ToList();

        ctrl.DisplayMember = "Value";
        ctrl.ValueMember = "Key";

        ctrl.SelectedValue = enum1;
    }



將枚舉轉換為字符串列表並將其添加到組合框

comboBox1.DataSource = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();

使用selectedItem設置顯示的值

comboBox1.SelectedItem = SomeEnum.SomeValue;



嘗試這個:

// fill list
MyEnumDropDownList.DataSource = Enum.GetValues(typeof(MyEnum));

// binding
MyEnumDropDownList.DataBindings.Add(new Binding("SelectedValue", StoreObject, "StoreObjectMyEnumField"));

StoreObject是我的StoreObjectMyEnumField屬性用於存儲MyEnum值的對象示例。




代碼

comboBox1.SelectedItem = MyEnum.Something;

沒問題,問題必須存在於DataBinding中。 DataBinding分配發生在構造函數之後,主要是第一次顯示組合框。 嘗試設置Load事件中的值。 例如,添加以下代碼:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    comboBox1.SelectedItem = MyEnum.Something;
}

並檢查它是否有效。




在Framework 4中,您可以使用以下代碼:

要將MultiColumnMode枚舉綁定到組合框,例如:

cbMultiColumnMode.Properties.Items.AddRange(typeof(MultiColumnMode).GetEnumNames());

並獲得選定的索引:

MultiColumnMode multiColMode = (MultiColumnMode)cbMultiColumnMode.SelectedIndex;

注意:在這個例子中,我使用DevExpress組合框,你可以在Win Form Combobox中做同樣的事情




晚會有點遲,

SelectedValue.ToString()方法應該拉入DisplayedName。 然而,這篇文章DataBinding枚舉和也與描述顯示了一個方便的方法,不僅有這個,而是你可以添加一個自定義的描述屬性的枚舉,並將其用於顯示值,如果你喜歡。 非常簡單和容易,大約15行左右的代碼(除非你計算大括號)。

這是非常漂亮的代碼,你可以使它成為引導的擴展方法...




這總是一個問題。 如果你有一個Sorted Enum,比如從0到...

public enum Test
      one
      Two
      Three
 End

您可以將名稱綁定到組合框,而不是使用.SelectedValue屬性使用.SelectedIndex

   Combobox.DataSource = System.Enum.GetNames(GetType(test))

Dim x as byte = 0
Combobox.Selectedindex=x



為了簡化:

首先初始化這個命令:(例如在InitalizeComponent()

yourComboBox.DataSource = Enum.GetValues(typeof(YourEnum))

檢索組合框上的選定項目
YourEnum enum = (YourEnum) yourComboBox.SelectedItem

如果你想為組合框設置值
yourComboBox.SelectedItem = YourEnem.Foo




public Form1()
{
    InitializeComponent();
    comboBox.DataSource = EnumWithName<SearchType>.ParseEnum();
    comboBox.DisplayMember = "Name";
}

public class EnumWithName<T>
{
    public string Name { get; set; }
    public T Value { get; set; }

    public static EnumWithName<T>[] ParseEnum()
    {
        List<EnumWithName<T>> list = new List<EnumWithName<T>>();

        foreach (object o in Enum.GetValues(typeof(T)))
        {
            list.Add(new EnumWithName<T>
            {
                Name = Enum.GetName(typeof(T), o).Replace('_', ' '),
                Value = (T)o
            });
        }

        return list.ToArray();
    }
}

public enum SearchType
{
    Value_1,
    Value_2
}



這是加載組合框中枚舉項的解決方案:

comboBox1.Items.AddRange( Enum.GetNames(typeof(Border3DStyle)));

然後使用枚舉項作為文本:

toolStripStatusLabel1.BorderStyle = (Border3DStyle)Enum.Parse(typeof(Border3DStyle),comboBox1.Text);



假設您有以下枚舉

public enum Numbers {Zero = 0, One, Two};

你需要一個結構來將這些值映射到一個字符串:

public struct EntityName
{
    public Numbers _num;
    public string _caption;

    public EntityName(Numbers type, string caption)
    {
        _num = type;
        _caption = caption;
    }

    public Numbers GetNumber() 
    {
        return _num;
    }

    public override string ToString()
    {
        return _caption;
    }
}

現在返回一個包含映射到字符串的所有枚舉的對像數組:

public object[] GetNumberNameRange()
{
    return new object[]
    {
        new EntityName(Number.Zero, "Zero is chosen"),
        new EntityName(Number.One, "One is chosen"),
        new EntityName(Number.Two, "Two is chosen")
    };
}

並使用以下內容填充組合框:

ComboBox numberCB = new ComboBox();
numberCB.Items.AddRange(GetNumberNameRange());

創建一個函數來檢索枚舉類型,以防萬一你想將它傳遞給一個函數

public Numbers GetConversionType() 
{
    EntityName type = (EntityName)numberComboBox.SelectedItem;
    return type.GetNumber();           
}

然後你應該沒問題:)




嘗試:

comboBox1.SelectedItem = MyEnum.Something;

EDITS:

哎呀,你已經試過了。 然而,當我的comboBox被設置為DropDownList時,它對我有效。

這裡是我的完整代碼(適用於DropDown和DropDownList):

public partial class Form1 : Form
{
    public enum BlahEnum
    { 
        Red,
        Green,
        Blue,
        Purple
    }

    public Form1()
    {
        InitializeComponent();

        comboBox1.DataSource = Enum.GetValues(typeof(BlahEnum));

    }

    private void button1_Click(object sender, EventArgs e)
    {
        comboBox1.SelectedItem = BlahEnum.Blue;
    }
}



目前我正在使用Items屬性而不是DataSource,這意味著我必須為每個枚舉值調用Add,但是它的一個小枚舉和它的臨時代碼無論如何。

然後,我可以對該值執行Convert.ToInt32並使用SelectedIndex進行設置。

臨時解決方案,但現在YAGNI。

歡呼的想法,我可能會使用它們,當我得到一輪客戶反饋後做適當的版本。







我使用以下幫助器方法,您可以綁定到您的列表。

    ''' <summary>
    ''' Returns enumeration as a sortable list.
    ''' </summary>
    ''' <param name="t">GetType(some enumeration)</param>
    Public Shared Function GetEnumAsList(ByVal t As Type) As SortedList(Of String, Integer)

        If Not t.IsEnum Then
            Throw New ArgumentException("Type is not an enumeration.")
        End If

        Dim items As New SortedList(Of String, Integer)
        Dim enumValues As Integer() = [Enum].GetValues(t)
        Dim enumNames As String() = [Enum].GetNames(t)

        For i As Integer = 0 To enumValues.GetUpperBound(0)
            items.Add(enumNames(i), enumValues(i))
        Next

        Return items

    End Function



正如其他人所說,在大多數情況下, ==.equals()工作。 編譯時的確定性,你沒有比較其他人指出的完全不同類型的對像是有效和有益的,但是FindBugs也可以找到比較兩種不同編譯時類型對象的特定類型的bug(可能是Eclipse / IntelliJ編譯時間檢查),所以Java編譯器發現它並不會增加額外的安全性。

然而:

  1. ==從來沒有拋出NPE的事實是==缺點 。 幾乎不需要enum類型為null ,因為您可能想要通過null表示的任何額外狀態都可以作為附加實例添加到enum中。 如果它意外為null ,我寧願有一個NPE而不是==默默評估為false。 所以我不同意它在運行時的意見是更安全的 ; 最好不要讓enum值為@Nullable
  2. == 更快的論點也是假的。 在大多數情況下,您會在編譯時類型為enum類的變量上調用.equals() ,在這種情況下,編譯器可以知道這與==相同(因為enumequals()方法可以不被覆蓋)並且可以優化功能呼叫。 我不確定編譯器目前是否這樣做,但如果不這樣做,並且總體上是Java性能問題,那麼我寧願修復編譯器,也不願意讓100,000個Java程序員改變他們的編程風格以適應一個特定的編譯器版本的性能特徵。
  3. enums是對象。 對於所有其他對像類型,標準比較是.equals() ,而不是== 。 我認為對enums進行例外是很危險的,因為您最終會意外地將對象與==而不是equals()相比較,特別是如果您將enum重構為非枚舉類。 在這種重構的情況下,上面的工作點是錯誤的。 要說服你自己使用==是正確的,你需要檢查有問題的值是一個enum還是一個原語; 如果它是一個非enum類,那就錯了,但很容易錯過,因為代碼仍然會編譯。 當使用.equals()會出錯時,唯一的情況是所討論的值是基元; 在那種情況下,代碼不會編譯,所以很難錯過。 因此, .equals()更容易識別為正確的,並且對未來的重構更安全。

我實際上認為Java語言應該已經在Object上定義了==來調用左側值的.equals(),並且為對象標識引入了一個單獨的運算符,但這不是Java定義的方式。

總之,我仍然認為參數贊成使用enum類型的.equals()





c# .net winforms combobox enums