如何使用 属性 网格编辑 winform UserControl 的复杂 属性

How to edit winform UserControl’s complex property with property grid

我创建了一个自定义用户控件,我想添加一个包含一些布尔值的新 属性。我不知道如何最好地解释它所以我将解释我想要实现的目标

在用户控件上有几个可见的按钮。
由于这是一个自定义用户控件,将其拖到窗体上的开发人员无法访问按钮,他只能看到它们并且只能访问自定义控件本身。
但是,为了使他能够将某些按钮设置为可见的错误,我想在可以执行此操作的自定义控件上制作一个 属性。
现在,假设我有 10 个按钮,我不想要 10 个 bool 属性来使每个按钮可见或不可见。
我只想要一个 属性,折叠打开,然后显示 10 个布尔类型的子属性(以及按钮的文本)

当我需要在自定义控件上添加或删除按钮时,这样对我来说会更容易。

它的工作方式类似于 Size 属性。
如果你折叠打开,你会得到 2 个数字子属性,widthheight
另一个很好的例子是 padding 属性,当它折叠打开时你会得到 5 个类型为 numeric

的子属性

我希望它像那样工作,但使用布尔属性而不是数字属性。

我一直在用谷歌搜索这个,但找不到怎么做,可能是因为我不知道这种 属性 的正确 term 叫法。

所以有人可以帮助我在正确的方向上如何做到这一点。

您可以使用 flags-attribute 创建一个枚举,其中每个值代表相应按钮的可见性。请参阅 Expose a collection of enums (flags) in Visual Studio designer 了解如何在 visual studio 设计器中公开它。

这个问题的公认答案对我来说看起来相当复杂。所以我可能会坚持制作 10 个独立的属性。您可以定义一个 category 来将它们全部放入以保持整洁。

我检查这个link

示例代码

[TypeConverter(typeof(BtnVisibilityConverter))]
public struct BtnVisibility
{
    public BtnVisibility(bool one, bool two, bool three)
    {
        One = one;
        Two = two;
        Three = three;
    }
    public bool One { get; set; }
    public bool Two { get; set; }
    public bool Three { get; set; }

    public override string ToString()
    {
        //check you logic here
        return "One Two Three";
    }
}

public class BtnVisibilityConverter : ExpandableObjectConverter
{
    public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
    {
        if (propertyValues != null
            && propertyValues.Contains("One")
            && propertyValues.Contains("Two")
            && propertyValues.Contains("Three")
            )
            return new BtnVisibility
            {
                One = (bool)propertyValues["One"],
                Two = (bool)propertyValues["Two"],
                Three = (bool)propertyValues["Three"]
            };
        return new BtnVisibility();
    }



    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor))
            return true;
        return base.CanConvertTo(context, destinationType);
    }
    public override object ConvertTo(ITypeDescriptorContext context,
        CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor))
        {
            ConstructorInfo ci = typeof(BtnVisibility).GetConstructor(new Type[] { typeof(string) });
            BtnVisibility t = (BtnVisibility)value;
            return new InstanceDescriptor(ci, new object[] { t.One, t.Three, t.Three });
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

这将在 属性 网格中显示 属性 扩展器,如下所示