C# 全局变量/常量可绑定到 DDL,但具有“Nice”功能名字

发布于 2024-11-25 09:44:53 字数 1367 浏览 4 评论 0原文

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

我考虑过的方法:

1)声明一个枚举:

public enum myOptions
{
  MyOption1 = 72,
  MyOption2 = 31,
  MyOption3 = 44
}

虽然这很适合编程,而且我可以将枚举直接绑定到 DDL,但是当用户看到它们时,枚举“名称”很丑陋 - 用户会看到“我的选项1”,我希望他们看到“我的选项#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 的常量,这样我就可以有一个漂亮的显示名称?

现在我唯一能想到的就是构建枚举和列表,这看起来很烦人。

For the usual reasons, I need to use some constants in my application.

The approaches I've considered:

1) Declare an Enum:

public enum myOptions
{
  MyOption1 = 72,
  MyOption2 = 31,
  MyOption3 = 44
}

While this is good to program against, and I can bind the enum directly to a DDL, but the Enum "names" are ugly when the user sees them - The user will see "MyOption1" and I want them to see "My Option #1".

2) Use a List:

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")
}

So while this binds very nicely to a DDL, gives me a nice display value as well as an integer return value, I don't have anything to test my return value against. So, for example:

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

3) I could build nice Global/Constants assembly:

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");
}

Which gives me nice display names, is nice to code against, but as far as I can tell there's no way for me to easily bind this to a DDL (I'd have to hand code it).

Does anyone have an elegant way of creating constants that are easily bound against a DDL, where I can have a nice display name?

Right now the only thing I can think of is building BOTH the Enum and the List, which seems annoying.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小鸟爱天空丶 2024-12-02 09:44:53

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

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;
}

I always lean toward decorated enum values:

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

or better yet you could create a custom attribute that would bind to a Resource file or a configuration setting so this data could be changed without recompiling

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

Update to generically pull attributes from an enum

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;
}
蓝戈者 2024-12-02 09:44:53

根据 @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 当前值匹配的项目。

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

Based on the answer provided by @hunter, I decided to post my full implementation since it took me a while to get it right (still learning here...)

// 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;
    }

}

Elsewhere, to do the binding to a DDL you can simply do this:

{
    // 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";      
}

Finally, to pull the selected value out you can do this:

{
    // 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();
}

..and I didn't stop there. I extended the ComboBox control itself, so binding it now is super-convenient.

    // 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;
    }

So now, whenever I want to populate a DDL, I just:

        myDDL.BindToDecoratedEnum(myEnumInstanceWithValue);

The code binds it, and selected the item that matches the current value of the Enum passed in.

Comments and criticism on my implementation is welcome (actually, I'd be thankful - like I said, I'm trying to learn...)

小女人ら 2024-12-02 09:44:53

另一个建议?

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();

Another Suggestion?

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;
    }

Then you can bind without having to create an instance of the enum. It is the type of enum you want information about, not a specific instance)

ddlPes.DataSource = EnumHelper.GetKeyValuePairs<PesId>();
ddlPes.DataValueField = "key";
ddlPes.DataTextField = "value";
ddlPes.DataBind();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文