views:

675

answers:

1

Hi,

I need to show an object in PropertyGrid with the following requirements: the object and its sub object must be read-only, able to activate PropertyGrid's CollectionEditors.

I found a sample that's closely match to what I need but there's an unexpected behaviour I couldn't figure out. I have more than one PropertyGrids each for different objects. In SetBrowsablePropertiesAsReadOnly, I loop one object but suprisingly all of PropertyGrids in my project become readonly. Can anybody help me out. Here's the code:



Imports System.Reflection
Imports System.ComponentModel

Public Class PropertyGridEx
    Inherits PropertyGrid

    Private isReadOnly As Boolean
    Public Property [ReadOnly]() As Boolean
        Get
            Return Me.isReadOnly
        End Get
        Set(ByVal value As Boolean)
            Me.isReadOnly = value
            Me.SetBrowsablePropertiesAsReadOnly(Me.SelectedObject, value)
        End Set
    End Property

    Protected Overloads Sub OnSelectedObjectsChanged(ByVal e As EventArgs)
        Me.SetBrowsablePropertiesAsReadOnly(Me.SelectedObject, Me.isReadOnly)
        MyBase.OnSelectedObjectsChanged(e)
    End Sub

    Private Sub SetBrowsablePropertiesAsReadOnly(ByRef selectedObject As Object, ByVal isReadOnly As Boolean)
        If selectedObject IsNot Nothing Then
            Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(selectedObject)
            For Each propDescript As PropertyDescriptor In props
                If propDescript.IsBrowsable AndAlso propDescript.PropertyType.GetInterface("ICollection", True) Is Nothing Then
                    Dim attr As ReadOnlyAttribute = TryCast(propDescript.Attributes(GetType(ReadOnlyAttribute)), ReadOnlyAttribute)
                    If attr IsNot Nothing Then
                        Dim field As FieldInfo = attr.[GetType]().GetField("isReadOnly", BindingFlags.NonPublic Or BindingFlags.Instance)
                        field.SetValue(attr, isReadOnly, BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, Nothing)
                    End If
                End If
            Next
        End If
    End Sub
End Class

A: 

The ReadOnly attribute is set on the class definition, not on an instance of an object. Hence this will have an impact on all instances of that class.

To achieve what you want, create a custom PropertyDescriptor in which you override the IsReadOnly property, and apply this to the properties of your object instance.

Vincent Van Den Berghe