【问题标题】:Property Grid Checkbox List Dropdown属性网格复选框列表下拉列表
【发布时间】:2021-09-03 13:55:38
【问题描述】:

我正在尝试将属性网格上的下拉列表转换为允许用户选择多个结果的复选框列表下拉列表。目前,我已经设法建立了一个用户可以选择的下拉选项列表,但它只允许用户选择一个。我希望用户选择超过 1 个选项,并且 Game_Type 字段将跟踪选择的内容,并用逗号分隔“射手,体育”等选项。我该怎么做?

预期的控件名称旁边应该有一个复选框,如下所示:

下面显示的代码包括一个游戏类、一个用于下拉列表的类型转换器以及创建对象并将其添加到属性网格的表单。

public class Game
{
    public string name { set; get; }

    [Browsable(false)]
    public List<string> listOfGameTypes { set; get; }

    [DisplayName("Game Type")]
    [TypeConverter(typeof(Game_Type_Converter))]
    public string Game_Type { get; set; }

    public Game()
    {
        listOfGameTypes = new List<string>();
    }
}

.

public class Game_Type_Converter : TypeConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        var obj = context.Instance as Game;

        if (obj != null)
        {
            List<string> list = new List<string>();
            foreach (String s in obj.listOfGameTypes)
            {
                list.Add(s);
            }
            return new StandardValuesCollection(list);
        }


        return base.GetStandardValues(context);
    }


}

.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Game g = new Game();
        g.name = "FIFA 22";
        g.listOfGameTypes.Add("Shooter");
        g.listOfGameTypes.Add("Sports");
        g.listOfGameTypes.Add("Action");

        propertyGrid1.SelectedObject = g;
    }
}

【问题讨论】:

  • 我不确定我是否同意你的评论... ” ...一个组合框下拉菜单,允许用户选择多个结果。” ...直观地说,组合框允许从众多选择中仅选择一 (1) 个。这是组合框的常见行为。如果你想创建一个如你所描述的那样,那么我的第一个问题是“如何”显示“哪些”项目被选中?此外,这对用户来说并不直观。这听起来像一个CheckedListBox 控件。我错过了什么吗?
  • 你是对的,它是一个 CheckedListBox 我想在这里申请。我刚刚意识到我在寻找错误的控制。我混淆了复选框和检查列表。我现在将尝试使用检查列表框找到解决方案。感谢您的帮助!
  • 仍然无法找到解决方案。
  • 你不能只使用 TypeConverter,你必须使用 UITypeEditor,像这样:stackoverflow.com/questions/40718467/…codeproject.com/Articles/23844/…

标签: c# propertygrid checklistbox


【解决方案1】:

以下内容转载自https://www.codeproject.com/Articles/13793/A-UITypeEditor-for-easy-editing-of-flag-enum-prope

我不是那篇文章的作者

由于这篇文章已经很老了,毫无疑问可以进行一些小的改进,例如使用 Enum.HasFlags


简介

Visual Studio .NET 中的设计时支持非常好,可以很容易地快速开发表单和用户控件。即便如此,它也有一些小缺点 - 有些令人讨厌,有些会造成不便。一个这样的缺点是缺乏在设计时属性浏览器中编辑“标志枚举属性”的好方法。标志枚举属性是其类型为应用了 FlagsAttribute 的枚举的属性。该属性表示可以将枚举视为位域;即一组标志。此类枚举的一个示例是 FontStyle 枚举。它包含粗体、斜体和下划线样式的位值,如果需要,可以将它们组合在一起。但是,属性网格没有对此类标志枚举的内置支持——如果你想指定你的字体应该是粗体和斜体,唯一的方法是编写等效的代码。

本文介绍了一个简单的 UITypeEditor,它可以应用于此类标志枚举,并使得使用设计时属性浏览器编辑此类属性变得非常容易。

背景

在讨论代码之前,有必要先简单介绍一下什么是UI Type Editor。在属性浏览器提供的简单的字符串到值和值到字符串的转换不充分或不方便的情况下,可以使用 UI 类型编辑器来提供用于编辑属性的高级 UI。例如,所有控件的 Dock 和 Anchor 属性都使用 UI 类型编辑器来轻松编辑属性。若要指定属性应使用 UI 类型编辑器,请将 EditorAttribute 应用于属性的类型或属性本身。在第一种情况下,只要属性具有应用属性的类型,就会使用 UI 类型编辑器。在第二种情况下,UI 类型编辑器仅用于该属性。

FlagEnumUIEditor 类

用于标志枚举的 UI 类型编辑器称为 FlagEnumUIEditor,它是从 UITypeEditor 派生的。它是一个下拉样式编辑器,这意味着在选择属性时,属性浏览器中会显示一个小型下拉按钮。单击此按钮时,将显示一个可用于编辑属性的控件。 FlagEnumUIEditor 使用派生自 CheckedListBox 的类来显示标志枚举。

FlagCheckedListBox 类

FlagCheckedListBox 类派生自 CheckedListBox,并包含 FlagCheckedListBoxItem 类型的项目。每个项目都有一个值和对应于枚举成员的值和名称的值的描述。 EnumValue 属性用于将枚举值与 FlagCheckedListBox 相关联:

public Enum EnumValue
{
    get
    {
        object e = Enum.ToObject(enumType,GetCurrentValue());
        return (Enum)e;
    }
    set
    {
        
        Items.Clear();
        enumValue = value; // Store the current enum value
        enumType = value.GetType(); // Store enum type
        FillEnumMembers(); // Add items for enum members
        ApplyEnumValue(); // Check/uncheck items depending on enum value
     }
}

FillEnumMembers 和 ApplyEnumValue 函数如下:

// Adds items to the checklistbox based on the members of the enum
private void FillEnumMembers()
{
    foreach ( string name in Enum.GetNames(enumType))
    {
        object val = Enum.Parse(enumType,name);
        int intVal = (int)Convert.ChangeType(val, typeof(int));

        Add(intVal,name);
    }
}

// Checks/unchecks items based on the current value of the enum variable
private void ApplyEnumValue()
{
    int intVal = (int)Convert.ChangeType(enumValue, typeof(int));
    UpdateCheckedItems(intVal);

}
        
// Checks/Unchecks items depending on the give bitvalue
protected void UpdateCheckedItems(int value)
{

    isUpdatingCheckStates = true;

    // Iterate over all items
    for(int i=0;i<Items.Count;i++)
    {
        FlagCheckedListBoxItem item = Items[i] as FlagCheckedListBoxItem;

        // If the bit for the current item is on in the bitvalue, check it
        if( (item.value & value)== item.value && item.value!=0)
            SetItemChecked(i,true);
        // Otherwise uncheck it
        else
            SetItemChecked(i,false);
    }

    isUpdatingCheckStates = false;

}

CheckListBox 的 OnItemCheck 函数被覆盖以在任何项目被选中或未选中时更新所有其他项目:

protected override void OnItemCheck(ItemCheckEventArgs e)
{
    base.OnItemCheck(e);

    if (isUpdatingCheckStates)
        return;

    // Get the checked/unchecked item
    FlagCheckedListBoxItem item = Items[e.Index] as FlagCheckedListBoxItem;
    // Update other items
    UpdateCheckedItems(item, e.NewValue);
}

// Updates items in the checklistbox
// composite = The item that was checked/unchecked
// cs = The check state of that item
protected void UpdateCheckedItems(FlagCheckedListBoxItem composite, 
                                  CheckState cs)
{

    // If the value of the item is 0, call directly.
    if(composite.value==0)
        UpdateCheckedItems(0);


    // Get the total value of all checked items
    int sum = 0;
    for(int i=0;i<Items.Count;i++)
    {
        FlagCheckedListBoxItem item = Items[i] as FlagCheckedListBoxItem;

        // If item is checked, add its value to the sum.
        if(GetItemChecked(i))
            sum |= item.value;
    }

    // If the item has been unchecked, remove its bits from the sum
    if(cs==CheckState.Unchecked)
        sum = sum & (~composite.value);
    // If the item has been checked, combine its bits with the sum
    else
        sum |= composite.value;

    // Update all items in the checklistbox based on the final bit value
    UpdateCheckedItems(sum);

}

最后,当用户编辑完属性后,使用GetCurrentValue方法返回CheckListBox中所有选中项对应的位值。

// Gets the current bit value corresponding to all checked items
public int GetCurrentValue()
{
    int sum = 0;

    for(int i=0;i<Items.Count;i++)
    {
        FlagCheckedListBoxItem item = 
                   Items[i] as FlagCheckedListBoxItem;

        if( GetItemChecked(i))
            sum |= item.value;
    }

    return sum;
}

使用代码

在您自己的项目中使用代码非常容易。只需将 FlagEnumEditor.cs 文件添加到您的项目中,然后将 UI 类型编辑器应用于您的枚举或属性,如下所示:

[Editor(typeof(Utils.FlagEnumUIEditor), 
    typeof(System.Drawing.Design.UITypeEditor))]

【讨论】:

    猜你喜欢
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多