Hi,
I am currently using the propertygrid control to browse an object containing many properties of different types, some being structures which contain properties of their own. The first problem is that when I create a class inheriting from ExpandableTypeConverter, and use this class as the type converter for a property in my base class, I cannot find a way to unbold the display text using the DefaultValue attribute... The second (more important) one is when I have one of these property (of the type of a user-defined structure) and I try to edit a property of the base property it does not change...The base property get method is just returning an unchanged version of the structure. Please let me know if this is a bug currently being resolved, or better, if there is a solution. (I've already checked some previous topics about the propertygrid). Thanks in advance.
Alex

PropertyGrid problems
chathuranga
Sorry about that - forgot you needed the other classes. Anyway, those steps you took were all correct - I can give you the PersonEditor now (the only extra class you would need) but the problem you noticed is the right one - and you can see it with the list (of person) fine... my only problem is that PersonRelations is a structure rather than a class, and so cannot contain a new with no arguments - also, i want to leave the father, mother, etc. as null as default.
Please let me know if you need the PersonEditor class, though I doubt you will. Anyway, thanks for the help so far. :)
Alex
wendy_yfl
OK, so I've done these so far:
- Copied your code for PersonRelations structure.
- Since you didn't provide Person and Creature definition, I created 2 classes for them, both with a simple property called Name.
- Since you didn't provide PersonEditor, I commented out the attributes with this class.
- Created a new class called Foo with your code for property Relations.
- Foo had a constructor that simply set rRelations = New PersonRelations.
Code for Foo:
Public Class Foo
Private rRelations As PersonRelations
<Category("Design"), _
Description("The relations to the person (father, mother, etc.)."), _
DefaultValue(False), TypeConverter(GetType(PersonRelationsConverter))> _
Public Property Relations() As PersonRelations
Get
Return rRelations
End Get
Set(ByVal value As PersonRelations)
rRelations = value
End Set
End Property
Public Sub New()
rRelations = New PersonRelations
End Sub
End Class
- Added a new Form1 with a PropertyGrid control. In my Load event handler, created a new Foo and set SelectedObject to it.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
m_Foo = New Foo
Me.PropertyGrid1.SelectedObject = m_Foo
End Sub
I observed that Relations.Father, Mother and Pets were empty and I could not edit them because I didn't have the editor. But I could edit Friends and added some new Person to the collection. Howerver, the collection was not persisted. Is this the issue you were talking about
I went back to Foo code and added the following to Foo constructor:
Public Sub New()
rRelations = New PersonRelations
rRelations.Father = New Person("Bob")
rRelations.Mother = New Person("Anne")
rRelations.Friends = New List(Of Person)
End Sub
With this, I observed that Relations.Father and Mother were not empty, but I could not edit them because I didn't have the editor. However, I could add Friends to the collection, change the Friends' names and everything were persisted. So, if the structure were initialized, changes would be persisted.
I'm not sure if this is the issue you're talking about. As you can see, even with the code you provided, I had to add more code and do additional steps to try to understand the issue. I'm willing to help, but there will be times when I can not go through the extra steps. Therefore, it would be best if you can provide code that can be copied, compiled and show the issue.
HTH,
picoSam
Thanks again - I will try changing the structure to a class ~ I wonder why it needs to be a class though :S. Anyway, I hope that will be solved but regarding the ConvertFrom method - I don't want the user to be able to edit the person by typing a string (box should be readonly) - is there a way to get around this
Regards,
Alex
_Donnie-Darko_
i don't really think there's much special code to it, but here is the important stuff:
Imports System.ComponentModel
Namespace
TypeConvertersPublic Class PersonRelationsConverter 'Expandable object provider for person relations
Inherits ExpandableObjectConverter
Public Overrides Function CanConvertTo(ByVal context As ITypeDescriptorContext, ByVal destinationType As Type) As Boolean
'Return true if can convert to destination type
If destinationType Is GetType(String) Then Return True
Return MyBase.CanConvertTo(context, destinationType)
End Function
Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
'Return value converted to destination type
If destinationType Is GetType(String) AndAlso TypeOf value Is Person.PersonRelations Then Return "(Relations)"
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
Public Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
'Return true if can convert from source type
If sourceType Is GetType(String) Then Return False
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As Globalization.CultureInfo, ByVal value As Object) As Object
'Return value converted from source type
Return MyBase.ConvertFrom(context, culture, value)
End Function
End Class
End Namespace
- this code may help you solve the 'bold' problem... the rest of the code is dotted all over the project and i don't think it will help much. anyway, thanks for replying :)
Regards, Alex
Ayres
please...i appreciate your help very much, i just can't seem to fins the solution :(
zenox
I checked and to be able to initialize Father, Mother as Null, you need to:
- Allow using string to represent Person, Creature, and other types you want to initialize to Null: In PersonTypeConverter, override CanConvertForm and return True when sourceType is String. Override ConvertFrom and convert a string to a Person and return it.
- Implement UITypeEditor, which is not a trivial process. 2 additional articles might help: http://msdn.microsoft.com/library/default.asp url=/library/en-us/dndotnet/html/usingpropgrid.asp and http://msdn.microsoft.com/library/default.asp url=/library/en-us/dndotnet/html/vsnetpropbrow.asp.
Regards,
nicope
Regards,
Sne
Public Sub New()
pFather = Nothing
pMother = Nothing
lFriends = New List(Of Person)
lPets = New List(Of Creature)
End Sub
thanks so far :)
DrJazz
Hi,
What I was hoping for was:
- A small class with a property of your user-defined structure type.
- A form using the property grid attempting to change this property for an object of this class.
- The plumbing neccessary to make the grid work.
- Something showing that the property is not changed correctly.
As you can see, no one so far has encountered the issue you described, so an immediate answer could not be provided. If you can narrow this down to some small repro code, I can try to debug it and / or ask the owner of the PropertyGrid about this issue. It would save a lot of time trying to reconstruct your issue from scratch.
Regards,
si-borg
Public Structure PersonRelations 'Relations of person Private pFather As Person 'Person ID of father Private pMother As Person 'Person ID of mother Private lFriends As List(Of Person) 'Person IDs of friends Private lPets As List(Of Creature) 'Creature IDs of pets
<Description("The father of the person (if known)."), _
DefaultValue(
False), Editor(GetType(PersonEditor), GetType(Drawing.Design.UITypeEditor))> _ Public Property Father() As Person Get Return pFather End Get Set(ByVal value As Person)pFather = value
End Set End Property<Description("The mother of the person (if known)."), _
DefaultValue(
False), Editor(GetType(PersonEditor), GetType(Drawing.Design.UITypeEditor))> _ Public Property Mother() As Person Get Return pMother End Get Set(ByVal value As Person)pMother = value
End Set End Property<Description("The friends of the person."), _
DefaultValue(
False)> _ Public Property Friends() As List(Of Person) Get Return lFriends End Get Set(ByVal value As List(Of Person))lFriends = value
End Set End Property<Description("The pets owned by the person."), _
DefaultValue(
False)> _ Public Property Pets() As List(Of Creature) Get Return lPets End Get Set(ByVal value As List(Of Creature))lPets = value
End Set End Property End Structureand the property:
<Category("Design"), _
Description("The relations to the person (father, mother, etc.)."), _
DefaultValue(
False), TypeConverter(GetType(PersonRelationsConverter))> _ Public Property Relations() As PersonRelations Get Return rRelations End Get Set(ByVal value As PersonRelations)rRelations = value
End Set End Propertythere's nothing special about the code in the form really...in fact the only code is to set the object - i get the error when i edit the property at run-time in debug mode...
StjSm
Imports System.ComponentModel
Namespace TypeConverters Public Class PersonListConverter 'Type converter for person list class Inherits TypeConverter Public Overrides Function CanConvertTo(ByVal context As ITypeDescriptorContext, ByVal destinationType As Type) As Boolean 'Return true if can convert to destination type If destinationType Is GetType(String) Then Return True Return MyBase.CanConvertTo(context, destinationType) End Function Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object 'Return value converted to destination type If destinationType Is GetType(String) AndAlso TypeOf value Is List(Of Person) Then Dim lList As List(Of Person) = value Return "(" & lList.Count & ")" End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function Public Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean 'Return true if can convert from source type If sourceType Is GetType(String) Then Return True Return MyBase.CanConvertFrom(context, sourceType) End Function Public Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As Globalization.CultureInfo, ByVal value As Object) As Object 'Return value converted from source type If TypeOf value Is String Then Return Nothing Return MyBase.ConvertFrom(context, culture, value) End Function End Class
End
NamespaceAnd thanks for pointing out the UITypeEditor - but in fact I already have that implemented and working. :)
Alex
David Bishop
In function ConvertFrom above, you did not convert a value from String to Person.
If TypeOf value Is String Then Return Nothing
so typing in a string won't give you a new Person.
I tried PersonTypeConverter and it worked for me, but only if PersonRelations was a class, not a structure. When I typed in a new value for PersonRelations.Father, my breakpoint in the Set statement was hit in both cases. But if PersonRelations was a structure, its Father property went back to Null later.
I do not have full knowledge of how the PropertyGrid works. The Windows Forms General forum (http://forums.microsoft.com/msdn/ShowForum.aspx ForumID=8) may be a better place to get that information. But notice that structure is passed around as ByVal, not ByRef. I think that's why you failed to initialize new values to the structure. I recommend using class in this case.
Regards,
Radexx
greenie