Setting properties for user control in "Properties" window of form

kejpa

Junior Contributor
Joined
Oct 10, 2003
Messages
320
Hi,
I have a property which contains an upper/lower combination that I have declared my own structure for.
How do I make it editable in the properties window when I put my control on a form?
It's visible, but I can't set the values, I want it to show up just like the location with a small + that expands to show Upper and Lower values.

TIA
/Kejpa
 
I recently tried to-do this and had alot of trouble finding the right information, but its not too difficult when you know how... Heres the c# code, if you'd prefer VB let me know and i'll try to convert it..

C#:
	internal class UpperLowerConverter : ExpandableObjectConverter
	{
		public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) 
		{
			return true;
		}

		public override object CreateInstance(ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) 
		{
			return new UpperLower ((int)propertyValues["Upper"], (int)propertyValues["Lower"]);
		}

		public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) 
		{
			// if main property node, create a string listing the 2 values (like the size struct etc)
			if (destinationType == typeof(string) && value is UpperLower) 
			{
				string myString = ((UpperLower)value).Upper + ", " + ((UpperLower)value).Lower;
				return myString;
			}

			return base.ConvertTo (context, culture, value, destinationType);
		}

	}

	/// <summary>
	/// A struct for holding a set of boolean values
	/// </summary>
	public struct UpperLower
	{
		private int _Upper, _Lower;
		
		public UpperLower(int iUpper, int iLower) 
		{
			_Upper = iUpper;
			_Lower = iLower;
		}

		
		[Browsable(true),
		DefaultValue(0), 
		Description("Gets or sets the lower value")]
		public bool Lower 
		{
			get { return _Lower; }
			set { _Lower = value; }
		}

		
		[Browsable(true),
		DefaultValue(10), 
		Description("Gets or sets the upper")]
		public bool Upper 
		{
			get { return _Upper; }
			set { _Upper = value; }
		}
	}

Basically what this code does is create a TypeConverter to tell the PropertyGrid what todo with the Property. By default the PropertyGrid works with an instance of the property not the original property so every time an option is changed you need to reset the entire property. Also with this type converter you can display the information you wish in the box rather than the UpperLower fully qualified name.

Sorry if that explanation isn't perfect but hopefully it'll help you do what your after.
 
Thanx!
I guess I could work it out in VB, but if you would post it I'd be very happy!

Regards
/Kejpa
 
I think its something like this... NB, I haven't tested it

Visual Basic:
imports System.ComponentModel

Public Class UpperLowerConverter
    Inherits System.ComponentModel.ExpandableObjectConverter

    Public Overloads Overrides Function GetCreateInstanceSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overloads Overrides Function CreateInstance(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal propertyValues As System.Collections.IDictionary) As Object
        Return New UpperLower(CInt(propertyValues("Upper")), CInt(propertyValues("Lower")))
    End Function

    Public Overloads Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
        If TypeOf destinationType Is String And TypeOf value Is UpperLower Then
            Dim myObj As UpperLower = CType(value, UpperLower)
            Dim myString As String = myObj.Upper & ", " & myObj.Lower
            Return myString
        End If

        Return MyBase.ConvertTo(context, culture, value, destinationType)

    End Function
End Class


Public Structure UpperLower

    Dim _Upper, _Lower As Single

    Public Sub New(ByVal iUpper As Single, ByVal iLower As Single)
        _Upper = iUpper
        _Lower = iLower
    End Sub

    <Browsable(True), DefaultValue(0), Description("Gets or sets the lower value")> _
       Public Property Lower() As Boolean
        Get
            Return _Lower
        End Get
        Set(ByVal Value As Boolean)
            _Lower = Value
        End Set
    End Property

    <Browsable(True), DefaultValue(10), Description("Gets or sets the upper")> _
    Public Property Upper() As Boolean
        Get
            Return _Upper
        End Get
        Set(ByVal Value As Boolean)
            _Upper = Value
        End Set
    End Property

End Structure
 
Sorry Cags :(
Somehow it won't work....

I changed one of the lines that wouldn't compile

Visual Basic:
       If TypeOf destinationType Is String And TypeOf value Is UpperLower Then
 ' Changed to...
       If destinationType Is Type.GetType("System.String") And TypeOf value Is UpperLower Then
Could that be the reason?

/Kejpa
 
What do you mean by it won't work, it won't compile, you can't edit it or something else?

EDIT:- I assume you are setting the TypeConverter of the property like so...

Visual Basic:
        <TypeConverter(GetType(UpperLower))> _
        Public Property Limits() As UpperLower
            Get
                Return _myLimits
            End Get
            Set(ByVal Value As UpperLower)
                _myLimits= Value
            End Set
        End Property

I just tested my code like that, it allows changing of properties, unfortunately the name doesn't change, I'm just lookint at that now.
 
Last edited:
Hi!
At first it wouldn't compile but then I changed the line as shown in my previos post and then it compiled.
But I still can't change the limits in the Properties window as I like. They appear dimmed, and act as read-only :(

I didn't have <TypeConverter(GetType(UpperLower))> on the property, I added it and it didn't make any difference.

Really appreciates all the help I get!
/Kejpa
 
I never noticed as I was typing it at the time, but the value passed to GetType should be the TypeConverter class not the actual type of the structure. I don't know if you realised that, so what my previous post should have said is

Visual Basic:
 <TypeConverter(GetType(UpperLowerConverter))> _

I guess thats my fault for not doublechecking my post.
 
Just to confirm things as this post has been abit disjointed, all the code pieces you need are as follows...

Your custom control class should have a property like so
Visual Basic:
Imports System.ComponentModel
Public Class LimitControl
    Inherits System.Windows.Forms.TextBox

    Dim myLimits As UpperLower

    <TypeConverter(GetType(UpperLowerConverter))> _
    Public Property Limits() As UpperLower
        Get
            Return myLimits
        End Get
        Set(ByVal Value As UpperLower)
            myLimits = Value
        End Set
    End Property
End Class
You will also need your structure
Visual Basic:
Imports System.ComponentModel
Public Structure UpperLower

    Dim _Upper, _Lower As Single

    Public Sub New(ByVal iUpper As Single, ByVal iLower As Single)
        _Upper = iUpper
        _Lower = iLower
    End Sub

    <Browsable(True), DefaultValue(0), Description("Gets or sets the lower value")> _
    Public Property Lower() As Single
        Get
            Return _Lower
        End Get
        Set(ByVal Value As Single)
            _Lower = Value
        End Set
    End Property

    <Browsable(True), DefaultValue(10), Description("Gets or sets the upper")> _
    Public Property Upper() As Single
        Get
            Return _Upper
        End Get
        Set(ByVal Value As Single)
            _Upper = Value
        End Set
    End Property

End Structure
and then you have your type converter
Visual Basic:
Imports System.ComponentModel
Public Class UpperLowerConverter
    Inherits System.ComponentModel.ExpandableObjectConverter

    Public Overloads Overrides Function GetCreateInstanceSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overloads Overrides Function CreateInstance(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal propertyValues As System.Collections.IDictionary) As Object
        Return New UpperLower(CInt(propertyValues("Upper")), CInt(propertyValues("Lower")))
    End Function

    Public Overloads Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
        If destinationType Is GetType(String) And TypeOf value Is UpperLower Then
            Dim myObj As UpperLower = CType(value, UpperLower)
            Dim myString As String = myObj.Upper & ", " & myObj.Lower
            Return myString
        End If

        Return MyBase.ConvertTo(context, culture, value, destinationType)

    End Function
End Class

With a bit of luck I haven't made any silly mistakes this time and this should clarify how it all works for you.
 
Back
Top