c#全局变量/常量可绑定到ddl,但带有"Nice"的名字

本文关键字:quot Nice 常量 全局变量 绑定 ddl | 更新日期: 2023-09-27 18:02:48

出于通常的原因,我需要在应用程序中使用一些常量。

我考虑过的方法:

1)声明一个Enum:
public enum myOptions
{
  MyOption1 = 72,
  MyOption2 = 31,
  MyOption3 = 44
}

虽然这是很好的编程,我可以将枚举直接绑定到DDL,但是枚举"名称"在用户看到它们时是丑陋的-用户将看到"MyOption1",而我希望他们看到"MyOption #1"。

2)使用列表:
public static List<KeyValuePair<int, string>> myOptions = new List<KeyValuePair<int, string>>
{
 new KeyValuePair<int, string>(77, "My Option #1"),
 new KeyValuePair<int, string>(31, "My Option #2"),
 new KeyValuePair<int, string>(44, "My Option #3")
}

因此,虽然这很好地绑定到DDL,为我提供了一个很好的显示值和一个整数返回值,但我没有任何东西可以测试我的返回值。例如:

if (selectedOption=????) //I'd have to hardcode the Key or Value I want to test for.

3)我可以建立一个很好的全局/常量程序集:

static myOptions
{
 public static KeyValuePair<int, string> MyOption1 = new new KeyValuePair<int, string>(77, "My Option #1");
 public static KeyValuePair<int, string> MyOption2 = new new KeyValuePair<int, string>(31, "My Option #2");
 public static KeyValuePair<int, string> MyOption3 = new new KeyValuePair<int, string>(44, "My Option #3");
}

给了我很好的显示名称,很好编写代码,但据我所知,我没有办法轻松地将其绑定到DDL(我必须手工编写它)。

有没有人有一个优雅的方法来创建常数,很容易绑定到DDL,在那里我可以有一个漂亮的显示名?

现在我唯一能想到的是同时构建Enum和List,这看起来很烦人。

c#全局变量/常量可绑定到ddl,但带有"Nice"的名字

我总是倾向于使用装饰的枚举值:

public enum myOptions
{
    [Description("My Option #1")]
    MyOption1 = 72,
    [Description("My Option #2")]
    MyOption2 = 31,
    [Description("My Option #3")]
    MyOption3 = 44
}

或者更好的是,您可以创建一个自定义属性,该属性将绑定到资源文件或配置设置,以便可以更改此数据而无需重新编译

public enum myOptions
{
    [Custom("MyOption1Key")]
    MyOption1 = 72,
    [Custom("MyOption2Key")]
    MyOption2 = 31,
    [Custom("MyOption3Key")]
    MyOption3 = 44
}

更新从枚举中一般地提取属性

public static T GetAttribute<T>(this Enum e) where T : Attribute
{
    FieldInfo fieldInfo = e.GetType().GetField(e.ToString());
    T[] attribs = fieldInfo.GetCustomAttributes(typeof(T), false) as T[];
    return attribs.Length > 0 ? attribs[0] : null;
}

根据@hunter提供的答案,我决定发布我的完整实现,因为我花了一段时间才把它弄对(仍然在这里学习…)

// This is the class I used to hold the extensions.
public static class EnumFunctions
{
    // Custom GetAttribute Extension - used to pull an attribute out of the enumerations.
    // This code is as per Hunter's answer, except I added the null check.
    public static T GetAttribute<T>(this Enum e) where T : Attribute
    {
        FieldInfo fieldInfo = e.GetType().GetField(e.ToString());
        // If the enumeration is set to an illegal value (for example 0,
        // when you don't have a 0 in your enum) then the field comes back null.
        // test and avoid the exception.
        if (fieldInfo != null)
        {
            T[] attribs = fieldInfo.GetCustomAttributes(typeof(T), false) as T[];
            return attribs.Length > 0 ? attribs[0] : null;
        }
        else
        {
            return null;
        }
    }
    // Custom GetKeyValuePairs - returns a List of <int,string> key value pairs with
    // each Enum value along with it's Description attribute.
    // This will only work with a decorated Enum. I've not included or tested what
    // happens if your enum doesn't have Description attributes.
    public static List<KeyValuePair<int, string>> GetKeyValuePairs(this Enum e)
    {
        List<KeyValuePair<int, string>> ret = new List<KeyValuePair<int, string>>();
        foreach (Enum val in Enum.GetValues(e.GetType()))
        {
            ret.Add(new KeyValuePair<int, string>(Convert.ToInt32(val), val.GetAttribute<DescriptionAttribute>().Description));
        }
        return ret;
    }
}

在其他地方,要绑定到DDL,可以简单地这样做:

{
    // We need an instance of the enum to call our extension method.
    myOptions o = myOptions.MyOption1;
    // Clear the combobox
    comboBox1.DataSource = null;
    comboBox1.Items.Clear();
    // Bind the combobox
    comboBox1.DataSource = new BindingSource(o.GetKeyValuePairs(), null);
    comboBox1.DisplayMember = "Value";
    comboBox1.ValueMember = "Key";      
}

最后,要把选中的值拉出来,可以这样做:

{
    // Get the selected item in the combobox
    KeyValuePair<int, string> selectedPair = (KeyValuePair<int, string>)comboBox1.SelectedItem;
    //I'm just sticking the values into text labels to demonstrate.
    lblSelectedKey.Text = selectedPair.Key.ToString();
    lblSelectedValue.Text = selectedPair.Value.ToString();
}

. .我并没有止步于此我扩展了ComboBox控件本身,所以现在绑定它是超级方便的。

    // Extends the Combobox control so that it can be automatically bound to an Enum
    // that has been decorated with Description attributes.
    // Sets the current value of the combobox to the value of the enum instance passed in.
    public static void BindToDecoratedEnum(this System.Windows.Forms.ComboBox cb, Enum e)
    {
        // Clear the combobox
        cb.DataSource = null;
        cb.Items.Clear();
        // Bind the combobox
        cb.DataSource = new System.Windows.Forms.BindingSource(e.GetKeyValuePairs(), null);
        cb.DisplayMember = "Value";
        cb.ValueMember = "Key";
        cb.Text = e.GetAttribute<DescriptionAttribute>().Description;
    }

现在,每当我想填充DDL时,我只需:

        myDDL.BindToDecoratedEnum(myEnumInstanceWithValue);

代码将其绑定,并选择与传入的Enum的当前值匹配的项。

欢迎对我的实现提出评论和批评(实际上,我很感激-就像我说的,我正在努力学习…)

还有什么建议吗?

public static List<KeyValuePair<int, string>> GetKeyValuePairs<T>()
    {
        Type enumType = typeof(T);
        List<KeyValuePair<int, string>> ret = new List<KeyValuePair<int, string>>();
        foreach (Enum val in Enum.GetValues(enumType))
        {
            ret.Add(
                new KeyValuePair<int, string>(Convert.ToInt32(val),
                val.GetAttribute<DescriptionAttribute>().Description)
                );
        } return ret;
    }

则无需创建枚举实例即可进行绑定。它是您想要获取信息的枚举类型,而不是特定的实例)

ddlPes.DataSource = EnumHelper.GetKeyValuePairs<PesId>();
ddlPes.DataValueField = "key";
ddlPes.DataTextField = "value";
ddlPes.DataBind();