【问题标题】:c# enum names to filter on in a DropDownList instead of valuec# 在 DropDownList 中过滤的枚举名称而不是值
【发布时间】:2017-08-15 22:18:30
【问题描述】:

我有一个枚举列表,其中包含一个名为 Default 的枚举。

public enum Fruits { Default = Banana, 
                    Banana = 1, 
                    Orange = 2, 
                    Grapefruit = 3 }

我需要填充一个不包括默认字段的下拉列表。

Html.DropDownList("fruitSelector", 
                Enum.GetValues(typeof(Fruits)).Cast<Fruits>()
                    .OrderBy(o => o.GetDescription())
                    .Where(o => o != Fruits.Default)
                    .Select(o => new SelectListItem() {Text = o.GetDescription(), Value = ((int) o).ToString()}), "-- All Fruits --",
                new {@class = "form-control", @aria_describedby="sizing-addon1"})

当我尝试过滤 Fruits.Default 时,它会同时删除默认值和 Banana。如何在仅删除默认值的情况下进行过滤器比较?

[[CORRECTION]] 这个枚举重复了我的问题。老实说,我不明白其中的区别。

public enum Fruits
    {
        Default = Peaches,
        Peaches = 1,
        Bananas = 2,
        Grapefruit = 3,
        Apple = 101,
        Watermellon = 102
    }

public enum Fruits2
{
    Default = Mangos,
    Mangos = 1,
    Dates = 2,
    Figs = 3,
    Apples = 101,
    Limes = 102,
    Grapes = 103
}

【问题讨论】:

  • 上面的代码能编译吗?还是您有此处未显示的扩展方法?否则o.GetDescription() 怎么编译不出错?
  • @Sach ya 这是一种获取自定义 Description 注释的方法。你可以排除它。

标签: c# asp.net-mvc enums


【解决方案1】:

我不认为你试图做的事情是可能的因为它是。问题在于您的 Enum 结构。

public enum Fruits
{
    Default = Peaches,
    Peaches = 1,
    Bananas = 2,
    Grapefruit = 3,
    Apple = 101,
    Watermellon = 102
}

您说Default 的值是Peaches,而其中的值又是1。这与(BPeachesADefault 基本相同:

int B = 1;
int A = B;

因此,当我们使用Enum.Parse() 时,它会将两者视为相同,并选择第一个值。当您查看以下场景时,您就会明白。使用您当前的 Enum 运行以下代码:

var deflt = Enum.Parse(typeof(Fruits), Fruits.Default.ToString());
var peach = Enum.Parse(typeof(Fruits), Fruits.Peaches.ToString());
Console.WriteLine(deflt);
Console.WriteLine(peach);

输出将是:

默认

默认

然后将您的枚举更改为:

public enum Fruits
{
    Peaches = Default ,
    Default = 1,
    Bananas = 2,
    Grapefruit = 3,
    Apple = 101,
    Watermellon = 102
}

然后再次运行上面两行代码。你这次的输出将是:

桃子

桃子

也就是说,Parse() 选择第一个定义的枚举,当有像你这样的相等时。

编辑:

上面的解释有点不正确,正如 George Alexandria 在下面的 cmets 中指出的那样。请看他的解释: 当使用 Peaches = Default , Default = 1 和 Default = Peaches, Peaches = 1 时你有不同的输出,因为你在 Console.WriteLine 中调用了 Enum.ToString。如果您查看 var deflt, var peach 您会发现它们在两种情况下都是相同的,并且它们是名称按字母顺序排列的第一个值。


但是有一个解决方法。从您的初始代码示例中,我收集到的是您需要一个枚举列表、它们的描述和它们的数值,对吗?所以,我首先会获取一个 strings 列表,不包括 Default,这很简单。然后遍历字符串列表,并添加到您的 SelectListItem 类对象列表中。

var res = Enum.GetNames(typeof(Fruits))
    .Where(x => x != "Default");

List<SelectListItem> list = new List<SelectListItem>();
foreach (string fruit in res)
{
    string desc = EnumHelper<Fruits>.GetEnumDescription(fruit); // This is a utility method I use. You can get the description using your extension method.
    int val = (int)Enum.Parse(typeof(Fruits), fruit);
    list.Add(new SelectListItem { enumName = fruit, enumDesc = desc, enumVal = val });
}

如果您必须拥有该OrderBy,则在创建SelectListItem 列表后,再次按Description 对其进行排序。

【讨论】:

  • 在使用Peaches = Default , Default = 1,Default = Peaches, Peaches = 1, 时会有不同的输出,因为您在Console.WriteLine 中调用了Enum.ToString。如果您查看var deflt, var peach,您会发现它们在两种情况下都是相同的,并且它们是 name 按字母顺序排列的第一个值
  • 这很有趣!谢谢!我会用这些信息更新我的答案。
  • 枚举已在使用中,无法更改。另外,以这种方式更改枚举没有多大意义..使用默认值的原因我相信现有代码是有一种简单的方法可以在需要时更改默认值。但是现有值的值不能改变。所以让 peach = default 与说 default = peach 有很大的不同。因此,除了使用您的解决方法之外,没有其他方法可以完成此操作吗?嗯
  • @Sach 我如何让扩展方法代替您为获取描述而编写的方法。意思是,没有枚举你这样做的方式,那么如何使用我可用的扩展描述。参考这一行: string desc = EnumHelper.GetEnumDescription(fruit);
  • 我假设您有自己的扩展方法,这就是您在回应我之前的评论时所说的。我不确定扩展方法,但欢迎您使用utility method I usually use,我最初也是从 SO 答案中获得的。
【解决方案2】:

您应该按名称比较枚举值,因为DefaultBanana 是相等的。因此,只需尝试检索名称、过滤它们并将它们解析为值。

var res = Enum.GetNames(typeof(Fruits))
              .Where(o => o != nameof(Fruits.Default))
              .Select(o => Enum.Parse(typeof(Fruits), o))
              .Cast<Fruits>().ToList();

这是您的完整示例:

Html.DropDownList("fruitSelector",
            Enum.GetNames(typeof(Fruits))
                .Where(o => o != nameof(Fruits.Default))
                .Select(o => Enum.Parse(typeof(Fruits), o)).Cast<Fruits>()
                .OrderBy(o => o.GetDescription())
                .Select(o => new SelectListItem() { Text = o.GetDescription(), Value = ((int)o).ToString() }), "-- All Fruits --",
            new { @class = "form-control", @aria_describedby = "sizing-addon1" })

【讨论】:

  • 这似乎适用于我放入的第一个枚举......但我注意到那个枚举没有复制我的问题......我添加了第二个略有不同的枚举......但打破了你的解决方案。老实说,我不明白为什么。 tx 为您提供帮助
  • 这个解决方案给出了苹果、香蕉、葡萄柚、默认值、西瓜……所以桃子不会出现,但默认值会出现。
  • @user1161137 你的第一个枚举是有效的,因为Banane 按字母顺序排列Default,但PeachesDefault 大,所以当你尝试解析1,Parse 返回按名称命名的较小值。对于第二个枚举,它是 Default
  • @user1161137 如果您正在寻找第二个枚举的解决方案,您可以在 Sach 答案中尝试解决方法。
  • 是的,我正在处理第二个枚举。我只是没有将问题正确地转换为堆栈。我不是在处理水果:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
  • 2022-10-03
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多