Jump to content
Xtreme .Net Talk

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


Recommended Posts

Posted

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

Posted

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..

 

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.

Anybody looking for a graduate programmer (Midlands, England)?
Posted

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

 

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

Anybody looking for a graduate programmer (Midlands, England)?
Posted

Sorry Cags :(

Somehow it won't work....

 

I changed one of the lines that wouldn't compile

 

      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

Posted (edited)

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...

 

       <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.

Edited by Cags
Anybody looking for a graduate programmer (Midlands, England)?
Posted

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

Posted

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

 

<TypeConverter(GetType(UpperLowerConverter))> _

 

I guess thats my fault for not doublechecking my post.

Anybody looking for a graduate programmer (Midlands, England)?
Posted

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

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

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

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.

Anybody looking for a graduate programmer (Midlands, England)?

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...