只读 PropertyGrid

发布于 2024-07-09 14:30:59 字数 1948 浏览 7 评论 0原文

我需要在 PropertyGrid 中显示一个对象,并满足以下要求:该对象及其子对象必须是只读的,能够激活 PropertyGrid 的 CollectionEditors。

我找到了一个与我需要的非常匹配的示例,但有一个我无法弄清楚的意外行为。 我有多个 PropertyGrid,每个 PropertyGrid 用于不同的对象。 在 SetBrowsablePropertiesAsReadOnly 中,我循环一个对象,但令人惊讶的是我的项目中的所有 PropertyGrid 都变为只读。 有人可以帮我吗。 这是代码:



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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

〆一缕阳光ご 2024-07-16 14:30:59

ReadOnly 属性是在类定义上设置的,而不是在对象实例上设置的。 因此,这将会对该类的所有实例产生影响。

要实现您想要的效果,请创建一个自定义 PropertyDescriptor,在其中重写 IsReadOnly 属性,并将其应用到对象实例的属性。

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.

抱猫软卧 2024-07-16 14:30:59

我确信这不是正确的 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

I'm sure this is not correct vb syntax but this can be done by adding an attribute:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文