PropertyGrid только для чтения - PullRequest
2 голосов
/ 15 декабря 2008

Мне нужно показать объект в PropertyGrid со следующими требованиями: объект и его подобъект должны быть доступны только для чтения, чтобы иметь возможность активировать PropertyGrid's CollectionEditors.

Я нашел образец, который близко соответствует тому, что мне нужно, но есть неожиданное поведение, которое я не мог понять. У меня есть несколько PropertyGrids для каждого объекта. В SetBrowsablePropertiesAsReadOnly я зацикливаю один объект, но удивительно, что все PropertyGrids в моем проекте становятся доступными только для чтения. Кто-нибудь может мне помочь. Вот код:



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

Ответы [ 2 ]

0 голосов
/ 04 января 2012

Я уверен, что это неправильный синтаксис vb, но это можно сделать, добавив атрибут:

Private Sub SetBrowsablePropertiesAsReadOnly(ByRef selectedObject As Object, ByVal isReadOnly As Boolean)
  If selectedObject IsNot Nothing Then
    TypeDescriptor.AddAttributes(selectedObject, New Attribute[] { New ReadOnlyAttribute(isReadOnly) });
  End If
End Sub
0 голосов
/ 04 марта 2009

Атрибут ReadOnly устанавливается в определении класса, а не в экземпляре объекта. Следовательно, это повлияет на все экземпляры этого класса.

Чтобы достичь желаемого, создайте пользовательский PropertyDescriptor, в котором вы переопределите свойство IsReadOnly и примените его к свойствам экземпляра вашего объекта.

...