PropertyGrid problems

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



Answer this question

PropertyGrid problems

  • chathuranga

    Hey,
    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

    Hi,

    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_

    hi,
    i don't really think there's much special code to it, but here is the important stuff:

    Imports System.ComponentModel

    Namespace TypeConverters

    Public 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

    *bump*
    please...i appreciate your help very much, i just can't seem to fins the solution :(

  • zenox

    Is it possible to convert PersonRelations to a class

    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

    Can you provide some simplified repro code for this issue That will help with finding out the answers.

    Regards,

  • Sne

    hmm...i just tried changing PersonRelations to a class, adding a sub New and now it displays no text as a value and the property isn't expandable. maybe i am doing something wrong here.

    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

    ok, sure - i hope this is enough along with the previous code :)

    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 Structure
     



    and 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 Property
     


    there'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

    I have just tried the PersonTypeConverter idea and it doesn't seem to work. This is my code:

    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 Namespace
     


    And thanks for pointing out the UITypeEditor - but in fact I already have that implemented and working. :)

    Alex


  • David Bishop

    Hi,

    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

    I've only made a very simple one, but I did find some great information at http://www.codeproject.com/vb/net/using_propertygrid.asp .  A two-part article that explains quite a bit and has some detailed examples.
  • greenie

    thanks very much for replying :) in fact, that was the first page about the propertygrid that i found, and i've taken everything i could from it...
  • PropertyGrid problems