kejpa Posted January 4, 2006 Posted January 4, 2006 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 Quote
Cags Posted January 4, 2006 Posted January 4, 2006 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. Quote Anybody looking for a graduate programmer (Midlands, England)?
kejpa Posted January 4, 2006 Author Posted January 4, 2006 Thanx! I guess I could work it out in VB, but if you would post it I'd be very happy! Regards /Kejpa Quote
Cags Posted January 4, 2006 Posted January 4, 2006 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 Quote Anybody looking for a graduate programmer (Midlands, England)?
kejpa Posted January 5, 2006 Author Posted January 5, 2006 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 Quote
Cags Posted January 5, 2006 Posted January 5, 2006 (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 January 5, 2006 by Cags Quote Anybody looking for a graduate programmer (Midlands, England)?
kejpa Posted January 9, 2006 Author Posted January 9, 2006 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 Quote
Cags Posted January 9, 2006 Posted January 9, 2006 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. Quote Anybody looking for a graduate programmer (Midlands, England)?
Cags Posted January 9, 2006 Posted January 9, 2006 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. Quote Anybody looking for a graduate programmer (Midlands, England)?
kejpa Posted January 10, 2006 Author Posted January 10, 2006 Yee! Thanks Cags, it's working now :) Best regards /Kejpa Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.