Problem with W32 PropertyGrid in WPF

MHanke

Member
Joined
Jan 14, 2009
Messages
7
Programming Experience
Beginner
Hello,

I've got a little problem. I've added a PropertyGrid in an WindowsFormsHost to my WPF Form.

When I set a control to the SelectedObject property of my pGrid, several control-properties are disabled. One of them is the Content Property, Tooltip... properties which are not readonly...

Does anyone know how I can edit this too, or where does that come from ?
 
It's because the Tooltip property (inherited FrameworkElement) is type Object, and the property also doesn't have a TypeConverter.
 
It's because the Tooltip property (inherited FrameworkElement) is type Object, and the property also doesn't have a TypeConverter.

Thanks so far for that answer. Is it possible to access this property in the grid and maybe change this ? Like typecast or something
 
Last edited:
It is possible, but needs some advanced code. The PropertyGrid uses the type system to get information about the selected object, by inheriting CustomTypeDescriptor class it is possible to write a wrapper class that returns customized type information for the wrapped object. Such a class can look like this:
VB.NET:
Public Class WrapDescriptor
    Inherits CustomTypeDescriptor
    Public mComponent As Object

    Public Sub New(ByVal component As Object)
        MyBase.New(TypeDescriptor.GetProvider(component).GetTypeDescriptor(component))
        mComponent = component
    End Sub

    Public Overloads Overrides Function GetProperties(ByVal attributes As Attribute()) As PropertyDescriptorCollection
        Dim inPdc As PropertyDescriptorCollection = MyBase.GetProperties(attributes)

        Dim pdcs As PropertyDescriptor() = New PropertyDescriptor(inPdc.Count - 1) {}
        For i As Integer = 0 To pdcs.Length - 1
            If inPdc(i).PropertyType Is GetType(Object) Then
                pdcs(i) = New StringObjectPropertyDescriptor(inPdc(i))
            Else
                pdcs(i) = inPdc(i)
            End If
        Next

        Return New PropertyDescriptorCollection(pdcs, True)
    End Function

    Public Overloads Overrides Function GetProperties() As PropertyDescriptorCollection
        Return GetProperties(Nothing)
    End Function
    
End Class
The GetProperties method is here the key to return custom property information, in this case we're going wild with all properties of Object type to return a custom PropertyDescriptor that can edit the value as a String. If the value is not editable as a string something will probably crash :p

When inheriting PropertyDescriptor you get to fill out several MustOverride members, they are not interesting for us so they all are set to return the default descriptor value. What is interesting is overriding the Converter property, here we can return a StringConverter, which is an inherited TypeConverter that handles conversion between object and String. Here is the StringObjectPropertyDescriptor class code:
VB.NET:
Public Class StringObjectPropertyDescriptor
    Inherits PropertyDescriptor
    Private mParent As PropertyDescriptor

    Public Sub New(ByVal parent As PropertyDescriptor)
        MyBase.New(parent)
        mParent = parent
    End Sub

    Public Overrides ReadOnly Property Converter() As System.ComponentModel.TypeConverter
        Get
            Return New StringConverter
        End Get
    End Property

    ' all  (MustInherit) members below return default results (using 'parent' property descriptor)

    Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
        Return mParent.CanResetValue(component)
    End Function

    Public Overrides ReadOnly Property ComponentType() As System.Type
        Get
            Return mParent.ComponentType
        End Get
    End Property

    Public Overrides Function GetValue(ByVal component As Object) As Object
        Return mParent.GetValue(component)
    End Function

    Public Overrides ReadOnly Property IsReadOnly() As Boolean
        Get
            Return mParent.IsReadOnly
        End Get
    End Property

    Public Overrides ReadOnly Property PropertyType() As System.Type
        Get
            Return mParent.PropertyType
        End Get
    End Property

    Public Overrides Sub ResetValue(ByVal component As Object)
        mParent.ResetValue(component)
    End Sub

    Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
        mParent.SetValue(component, value)
    End Sub

    Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
        Return mParent.ShouldSerializeValue(component)
    End Function
End Class
So when you select the object for PropertyGrid you just wrap it into a new WrapDescriptor instance like this:
VB.NET:
pg.SelectedObject = New WrapDescriptor(Me.Button1)
 
If you search the web you will see many hits for "wpf propertygrid", I guess there are many other problems with wpf controls and the prop.grid to solve. You should have a look around also, the above example was just a quick & dirty solution to add a StringConverter to Object type properties, other (better) solutions could emerge from a web lookup.
 
Back
Top