Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a Property with Browsable, Expandable Fields

To clarify what I am asking, look at the Font property in the designer. When you click its dropdown, you get the options ForeColor, ImeMode, Language, etc.

I want the same kind of dropdown that allows me to enter in several values for a property I am adding to the designer myself (It will be for a database property in my custom control and give you an option to select Version, Type, etc.).

How would I go about doing this? I've looked all over and I can't find a solution.

Thank you.

like image 843
cjw Avatar asked Mar 14 '23 21:03

cjw


2 Answers

What you are looking for is provided by a TypeConverter. Specifically, you need an ExpandableObjectConverter - this "breaks out" the child properties. My fake type - it is a stand-in for your control:

Public Class Widget
    Public Property Name As String
    Public Property FooValue As Integer

    Public Property XYOffset As Offset
     ...

Offset is itself a Type made up of three properties:

Public Class Offset
    Public Property Name As String
    Public Property X As Int32
    Public Property Y As Int32
    ...
    Public Overrides Function ToString() As String
        Return String.Format("{0}: ({1}, {2})", Name, X.ToString, Y.ToString)
    End Function

In case it is not clear, Widget would be your control, XYOffset would be the property you are asking about. The ToString() overrides is so that you dont get the ugly Type name (WindowsApplication14.SomeType) in property grids. The result in a PropertyGrid control:

enter image description here

It is disabled and because NET doesnt know how to edit an Offset object. This just requires one of the simplest TypeConverters:

Public Class XYOffsetConverter
    Inherits ExpandableObjectConverter

    ' more to come 
End Class

Decorate the property:

Public Class Offset
     ...
    <TypeConverter(GetType(XYOffsetConverter))>
    Public Property XYOffset As Offset

The Offset property could use: <TypeConverter(GetType(ExpandableObjectConverter))> but since you mentioned this is a CustomControl, you will need other functionality in your TypeConverter later (see Notes). The result is the core functionality with almost no work:

enter image description here

Since NET does know how to edit String and Int32 the edits work on the opened up properties. There are 2 things lacking in it:
a) As you edit the child properties, the Offset Property "summary" doesnt update (X doesnt match in the image)
b) The user cant edit the top 'summary' string to change the properties.

Fixing the first is easy. Just add an attribute to the Offset properties:

Public Class Offset
    <NotifyParentProperty(True)>
    Public Property Name As String
    <NotifyParentProperty(True)>
    Public Property X As Int32
    <NotifyParentProperty(True)>
    Public Property Y As Int32

Now, the summary updates after each child property edit:

enter image description here

Fixing B is not hard - you just have to parse the string you create in ToString() and return a new Offset from it. However it is not necessary, just nice, since they can open it and edit each value.

The other thing is that it depends on what those things are and I dont want to guess what your Type (Class) looks like. Most TypeConverters are type-specific and I have no idea what yours looks like.

I used a property grid for the examples, but a control would work the same in the VS property window.

Note
You indicated this was for a custom control. In that case, you will need to help VS serialize your Type because it will not know how to create an Offset Type created in the designer. This is another job for your TypeConverter. I just dont know what your looks like.

like image 62
Ňɏssa Pøngjǣrdenlarp Avatar answered Mar 18 '23 08:03

Ňɏssa Pøngjǣrdenlarp


You can use the TypeConverterAttribute with the System.ComponentModel.ExpandableObjectConverter class as it's parameter.

The attribute will convert your class into one which will be supported by the designer as a "drop down" property.

Example code:

Imports System.ComponentModel

<TypeConverterAttribute(GetType(System.ComponentModel.ExpandableObjectConverter))>
Public Class MyPropertyClass
    Public Property Name As String
    Public Property Value As Integer
End Class

And in your class which will contain the property:

<Browsable(True)> _
Public Property MyProperty As New MyPropertyClass

Result:

Drop down property.

like image 31
Visual Vincent Avatar answered Mar 18 '23 07:03

Visual Vincent