CheckedListBox是一个多选择器控件,是DevExpress提供的用以解决多选情况下的解决方案。

首先,我们需要一个面板Panel承载CheckedListBox,Panel使用DevExpress提供的PanelControl控件,设置停靠方式为在父容器上停靠,用代码控制为:this.PanelControl1.Dock=DockStyle.Fill,然后将CheckedListBox拖拽到Panel面板上,设置停靠方式为在父容器上停靠,最终效果如下即为正确:

打开网易新闻 查看更多图片

于是,我们需要初始化CheckedListBox,为其中加入我们需要添加的选择项。第一步我们先清空CheckedListBox的选择项,这样做是为了方便下次可以刷新。代码写为:

this.checkedListBoxControl1.Items.Clear();

接下来我们给CheckedListBox上添加选择项,当然可以一个一个添加,但是这里给出的解决方案是定义一个枚举类,先来看这个枚举类怎么定义的。这里给出石油生产的相关指标项。

  1. public enum ProdQuotaEnum
  2. /// 日产油
  3. [Display(Name = "日产油水平")]
  4. [Group(GroupName = "0")]
  5. DailyOil,
  6. /// 单井日产油水平
  7. [Display(Name = "单井日产油水平")]
  8. [Group(GroupName = "0")]
  9. WellDailyOil,
  10. /// 单井日产油能力
  11. [Display(Name = "单井日产油能力")]
  12. [Group(GroupName = "0")]
  13. WellDailyOilAbility,
  14. /// 平均单井日产油
  15. [Display(Name = "平均单井日产油水平")]
  16. [Group(GroupName = "0")]
  17. AverageDailyOil,
  18. /// 综合含水
  19. ///
  20. [Display(Name = "综合含水")]
  21. [Group(GroupName = "0")]
  22. TotalWaterCut,
  23. ///
  24. /// 注采比
  25. ///
  26. [Display(Name = "注采比")]
  27. [Group(GroupName = "0")]
  28. InjProdRatio,
  29. ///
  30. /// 综合生产油气比
  31. ///
  32. [Display(Name = "综合生产气油比")]
  33. [Group(GroupName = "0")]
  34. CompreProdRatio,
  35. ///
  36. /// 原油计量系统误差(输差)
  37. ///
  38. [Display(Name = "原油计量系统误差(输差)")]
  39. [Group(GroupName = "0")]
  40. CrudeOilMeteringSystemError
  41. }

其中Display属性提供允许实体分部类的类型和成员指定可本地化字符串的通用特性。Group属性是分组属性,可以用于一个枚举类上有多个种类的指标项,这样就可以筛选出多种选择项。但是CheckedListBox需要显示指标内容,于是我们需要获取枚举类的Display属性,这样我们需要额外定义一个工具类:AttributeHelper类。

  1. public static IEnumerable
  2. GetEnumWithKey
  3. (T t, string groupName)
  4. {
  5. var list = new List
  6. ();
  7. Type type = t.GetType();
  8. if (!type.IsEnum) return list;
  9. foreach (FieldInfo fd in type.GetFields())
  10. {
  11. object[] attrs = fd.GetCustomAttributes(typeof(GroupAttribute), false);
  12. if (attrs != null && attrs.Length > 0 && (attrs[0] as GroupAttribute).GroupName == groupName)
  13. {
  14. list.Add((T)fd.GetRawConstantValue());
  15. }
  16. }
  17. return list;
  18. }

这个方法是根据Group的值来映射出枚举类的Display属性值,但是用于CheckedListBox显示出指标内容,那么我们还需定义一个取display属性的方法:

  1. public static string GetEnumDisplayName
  2. (T t)
  3. {
  4. Type type = t.GetType();
  5. if (!type.IsEnum) return string.Empty;
  6. FieldInfo fd = type.GetField(t.ToString());
  7. if (fd == null)
  8. return string.Empty;
  9. object[] attrs = fd.GetCustomAttributes(typeof(DisplayAttribute), false);
  10. string name = string.Empty;
  11. foreach (DisplayAttribute attr in attrs)
  12. {
  13. name = attr.Name;
  14. break;
  15. }
  16. return name;
  17. }

准备好枚举类和取枚举类的属性工具类之后,就可以添加指标项了。代码这样写:

  1. var enumList1 = AttributeHelper.GetEnumWithKey(ProdQuotaEnum.AverageDailyOil, "0");
  2. foreach (var item in enumList1)
  3. {
  4. this.checkedListBoxControl1.Items.Add(new CheckedListBoxItem()
  5. Description = AttributeHelper.GetEnumDisplayName(item),
  6. Tag = item

GetEnumWithKey方法的参数为枚举类,以及Group属性值,获取到枚举类之后,然后遍历这个列表,然后将属性值一个一个地写入CheckedListBox,每一个选择项都是一个CheckedListBoxItem的对象,于是我们可以将Description属性设为Display属性,Tag设为每一个枚举类的值。写好这个我们运行下看下效果:

打开网易新闻 查看更多图片

可以看到指标项都添加进去了,然后我们需要进行多选,那么我们首先定义个迭代属性对象,用于保存用户选择的指标项。如下:

private IEnumerable selectItems = new List

接着我们需要定义CheckedListBox的选择事件,这里给出代码:

  1. this.checkedListBoxControl1.ItemCheck += CheckedListBoxControl1_ItemCheck;
  2. private void CheckedListBoxControl1_ItemCheck(object sender, DevExpress.XtraEditors.Controls.ItemCheckEventArgs e)
  3. this.UpdateSelectItems();

这里给方法里定义了一个UpdateSelectItems,用于实现用户每次点击之后程序获取用户的选择项,我们接下来就把这个方法实现下:

  1. private void UpdateSelectItems()
  2. selectItems = this.checkedListBoxControl1.Items.Where(x => x.CheckState == CheckState.Checked);
  3. if (!selectItems.Any()) this.checkedListBoxControl1.Items[0].CheckState = CheckState.Checked;
  4. foreach(var item in selectItems)
  5. Console.Write(item.Description + ",");

在这个方法中,第一行使用Where子句筛选出已经选中的指标项,第二句用于判断selectItems是否有值,如果没有就把第一个选中,然后遍历这个选中的指标项,然后在命令窗口上打印出来,我们来看最终效果:

打开网易新闻 查看更多图片