【问题标题】:How to edit winform UserControl’s complex property with property grid如何用属性网格编辑winform UserControl的复杂属性
【发布时间】:2021-05-25 14:24:07
【问题描述】:

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

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

这样,当我需要在自定义控件上添加或删除按钮时,我会更轻松。

它可以像 Size 属性一样工作。
如果您将其折叠打开,您将获得 2 个数字子属性,widthheight
另一个很好的例子是padding 属性,当它折叠打开时,你会得到 5 个数字类型的子属性

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

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

所以有人可以帮助我正确地执行此操作。

【问题讨论】:

  • 多个按钮合二为一UserControl?当然。要隐藏 10 个按钮,只需...隐藏用户控件?
  • @Sinatr 这没有意义,我不想隐藏用户控件,我想让一些按钮可见而一些不可见,这取决于用户控件将用于什么
  • 你想拥有uint 属性(足以容纳10位)和控制按钮的可见性设置位吗?
  • 试试标记枚举,你可以在一个属性中存储多个状态。
  • @GuidoG,当然,请参考stackoverflow.com/questions/8447/…

标签: c# winforms properties custom-controls


【解决方案1】:

我检查了这个链接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);
    }
}

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

【讨论】:

  • 这似乎是要走的路。谢谢你。我会尽快试试这个
  • 我更改了代码以使用我的名字而不是一二...并编译了它。代码与您在控件中添加属性 VisiblityProp 时的效果如何?
  • 它就像所有其他属性声明一样 public BtnVisibility VisibilityProp { get;放;您应该构建您的解决方案以在您的 propertyGrid 中反映这一点。 ***我没有实现基于属性隐藏按钮的逻辑(因为它取决于你的业务逻辑)
  • 还根据您的要求实现 ToString() 版本
【解决方案2】:

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

对我来说,这个问题的公认答案看起来相当复杂。所以我可能会坚持制作 10 个单独的属性。你可以定义一个category 来把它们都放进去,这样会让事情更整洁一些。

【讨论】:

  • 那么大小、边距、填充等属性是如何创建的呢?必须有某种方法可以用 bool 而不是 numeric
  • 现有属性的控件可能已经为它们内置了编辑器。但是,如果没有编辑器可用于您尝试做的事情,您必须自己编写。根据链接,似乎没有任意枚举标志的现有编辑器。
  • 所以这些属性在属性窗口中折叠打开,这是一个为大小、填充和边距属性制作的单独编辑器?我试图了解这些是如何工作的
  • @GuidoG,我发布了一个新答案。你可以检查
  • 毕竟我选择了 10 个独立的属性
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多