如何使用 属性 网格编辑 winform UserControl 的复杂 属性
How to edit winform UserControl’s complex property with property grid
我创建了一个自定义用户控件,我想添加一个包含一些布尔值的新 属性。我不知道如何最好地解释它所以我将解释我想要实现的目标
在用户控件上有几个可见的按钮。
由于这是一个自定义用户控件,将其拖到窗体上的开发人员无法访问按钮,他只能看到它们并且只能访问自定义控件本身。
但是,为了使他能够将某些按钮设置为可见的错误,我想在可以执行此操作的自定义控件上制作一个 属性。
现在,假设我有 10 个按钮,我不想要 10 个 bool 属性来使每个按钮可见或不可见。
我只想要一个 属性,折叠打开,然后显示 10 个布尔类型的子属性(以及按钮的文本)
当我需要在自定义控件上添加或删除按钮时,这样对我来说会更容易。
它的工作方式类似于 Size
属性。
如果你折叠打开,你会得到 2 个数字子属性,width
和 height
另一个很好的例子是 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);
}
}
这将在 属性 网格中显示 属性 扩展器,如下所示
我创建了一个自定义用户控件,我想添加一个包含一些布尔值的新 属性。我不知道如何最好地解释它所以我将解释我想要实现的目标
在用户控件上有几个可见的按钮。
由于这是一个自定义用户控件,将其拖到窗体上的开发人员无法访问按钮,他只能看到它们并且只能访问自定义控件本身。
但是,为了使他能够将某些按钮设置为可见的错误,我想在可以执行此操作的自定义控件上制作一个 属性。
现在,假设我有 10 个按钮,我不想要 10 个 bool 属性来使每个按钮可见或不可见。
我只想要一个 属性,折叠打开,然后显示 10 个布尔类型的子属性(以及按钮的文本)
当我需要在自定义控件上添加或删除按钮时,这样对我来说会更容易。
它的工作方式类似于 Size
属性。
如果你折叠打开,你会得到 2 个数字子属性,width
和 height
另一个很好的例子是 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);
}
}
这将在 属性 网格中显示 属性 扩展器,如下所示