0

I have created a custom user control, and I want to add a new property that contains a few bool values. I don't know how to explain it best so I will explain what I am trying to achieve

On the user control there are a few buttons visible.
Since this is a custom user control, a developer that drags it on a form cannot access the buttons, he can only see them and only access the custom control itself.
But, to enable him to put some buttons visible false, I want to make a property on the custom control that can do this.
Now, suppose I have 10 buttons, I don't want 10 bool properties to make each button visible or not.
I would like just one property, that folds open, and then shows 10 sub-properties of type boolean (and with the text of the button)

This way it will be easier for me when I need to add or remove buttons on the custom control.

It would work like for example the Size property.
If you fold that open, you get 2 numeric sub-properties, width and height
Another good example is the padding property, when this folds open you get 5 sub properties of type numeric

I want it to work like that, but with bool properties in stead of numeric properties.

I have been googling this but cannot find how to do it, propably because I don't know the correct term of how this kind of property is called.

So can someone please help me in the right direction of how to do this.

Biju Kalanjoor
  • 532
  • 1
  • 6
  • 12
GuidoG
  • 11,359
  • 6
  • 44
  • 79
  • Multiple buttons in one `UserControl`? Sure. To hide 10 buttons just ... hide user control? – Sinatr May 25 '21 at 14:30
  • @Sinatr That makes no sense, I dont want to hide the user control, i want to make some buttons visible and some not, depending on whatever the user control will be used for – GuidoG May 25 '21 at 14:31
  • Do you want to have `uint` property (enought to hold 10 bits) and control buttons visibility be setting bits? – Sinatr May 25 '21 at 14:31
  • Try Flagged Enum, you can store multiple state in one propery. – Biju Kalanjoor May 25 '21 at 14:31
  • @Sinatr I am not sure about this `uint` But anyway, it has to be possible to create such a property, how else are the size, the padding, the margin, ... created – GuidoG May 25 '21 at 14:32
  • @BijuKalanjoor I will look this up, if you have some good link or example that would be nice – GuidoG May 25 '21 at 14:33
  • *"the size, the padding, the margin"* - they ares simple `enum` or what do you mean? See [this answer](https://stackoverflow.com/a/64326/1997232) as an example (it's not about your topic, but shows enums with values and attributes for property panel in winforms designer). – Sinatr May 25 '21 at 14:35
  • 1
    @GuidoG, sure , please refer this https://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c – Biju Kalanjoor May 25 '21 at 14:36
  • @Sinatr when I use a simple `enum` I can only choose one value from a list, that is not what I want. I want it to work like th size, the padding or the margin property where you can set a value for each – GuidoG May 25 '21 at 14:36
  • MSDN link, https://learn.microsoft.com/en-us/dotnet/api/system.enum.hasflag?view=net-5.0 – Biju Kalanjoor May 25 '21 at 14:40
  • You need a TypeConverter. All the structs you have mentioned, use a dedicated TypeConverter to expose values that can be set in the Properties panel. You can collect your Buttons as usual (short version) `this.Controls.OfType – Jimi May 25 '21 at 15:07
  • @Jimi That sounds good, do you have some example or good documentation for this (not microsoft docs they are mostly useless) – GuidoG May 25 '21 at 15:08

2 Answers2

1

You could make a enum with the flags-attribute where each value represents the visibility of the corresponding button. See Expose a collection of enums (flags) in Visual Studio designer on how to expose this in the visual studio designer.

The accepted answer to that question looks rather complex to me. So I would probably stick to making 10 separate properties. You can define a category to put all of them in to keep things a bit neater.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • So how are propeties like size, margin, padding and so on create then ? There must be some method of doing the same with a bool in stead of numeric – GuidoG May 25 '21 at 14:57
  • Controls for existing properties probably have built in editors for them. But if no editor is available for what you are trying to do you have to write your own. According to the link there does not seem to be an existing editor for arbitrary enum flags. – JonasH May 25 '21 at 15:01
  • So that these propeties fold open in the property window, that is a seperate editor that was made for the size, the padding and the margin property ? I am trying to understand how these work – GuidoG May 25 '21 at 15:03
  • @GuidoG, I post a new answer . You can check – Biju Kalanjoor May 26 '21 at 08:24
  • I went for 10 separate properties after all – GuidoG Jul 03 '21 at 09:03
1

I check this link Link

Sample Code

[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);
    }
}

this will show the Property Expander in PropertyGrid like below

enter image description here

Biju Kalanjoor
  • 532
  • 1
  • 6
  • 12
  • 1
    This seems like the way to go. Thank you. I will try this as soon as possible – GuidoG May 26 '21 at 12:54
  • I altered the code to use my names in stead of One Two... and got it compiling. How does the code looks like that you used to add the property `VisiblityProp` in your control ? – GuidoG May 26 '21 at 15:15
  • Its just like all other property declaration public BtnVisibility VisibilityProp { get; set; } You should build your solution for refecting this in your propertyGrid. ***I didn't implement the logic for hiding the buttons based on the property (becase its upto you business logic) – Biju Kalanjoor May 26 '21 at 15:39
  • Also implement a ToString() Version based on your requirement – Biju Kalanjoor May 26 '21 at 15:43