首页 > 解决方案 > 隐藏表单的 DoubleBuffered 属性而不使其不起作用

问题描述

使用Class我试图DoubleBuffered从表单的属性窗口中隐藏该属性,但不使其不起作用。所以我在下面的代码示例中做了类似的事情......但是,DoubleBuffered属性仍然出现。那么,我们真的可以隐藏DoubleBuffered财产吗?如果可以,我们该怎么做呢?

Imports System.ComponentModel
Imports System.ComponentModel.Design

Public Class MyForm
    Inherits Form

    <Browsable(False)>
    Public Overloads Property DoubleBuffered As Boolean
        Get
            Return MyBase.DoubleBuffered
        End Get
        Set(ByVal value As Boolean)
            MyBase.DoubleBuffered = value
        End Set
    End Property

    Public Sub New()
        Me.DoubleBuffered = True
    End Sub

End Class

标签: vb.netvisual-studio-2017

解决方案


您可以为您的表单创建一个自定义组件设计器,但仅重新创建不可访问的功能是一项艰巨的任务System.Windows.Forms.Design.FormDocumentDesigner。更简单的方法是使用我之前向您展示过的表单的站点属性来访问设计器服务。

在这种情况下,您需要覆盖设计器主机的ITypeDescriptorFilterService服务。该服务由设计者用于所有类型发现/过滤操作,并且不限于特定组件。

第一步是创建一个实现ITypeDescriptorFilterService. 以下是一种这样的实现。它是一个通用实现,允许它过滤指定类型的组件并获取要从 PropertyGrid 显示中排除的属性名称列表。它需要的最后一项是对设计器宿主使用的现有服务的引用。

Friend Class FilterService(Of T) : Implements ITypeDescriptorFilterService
    Private namesOfPropertiesToRemove As String()

    Public Sub New(baseService As ITypeDescriptorFilterService, ParamArray NamesOfPropertiesToRemove As String())
        Me.BaseService = baseService
        Me.namesOfPropertiesToRemove = NamesOfPropertiesToRemove
    End Sub

    Public ReadOnly Property BaseService As ITypeDescriptorFilterService
    Public Function FilterAttributes(component As IComponent, attributes As IDictionary) As Boolean Implements ITypeDescriptorFilterService.FilterAttributes
        Return BaseService.FilterAttributes(component, attributes)
    End Function

    Public Function FilterEvents(component As IComponent, events As IDictionary) As Boolean Implements ITypeDescriptorFilterService.FilterEvents
        Return BaseService.FilterEvents(component, events)
    End Function

    Public Function FilterProperties(component As IComponent, properties As IDictionary) As Boolean Implements ITypeDescriptorFilterService.FilterProperties
        ' ref: ITypeDescriptorFilterService Interface: https://msdn.microsoft.com/en-us/library/system.componentmodel.design.itypedescriptorfilterservice(v=vs.110).aspx
        ' 
        ' The return value of FilterProperties determines if this set of properties is fixed.
        ' If this method returns true, the TypeDescriptor for this component can cache the 
        ' results. This cache is maintained until either the component is garbage collected or the Refresh method of the type descriptor is called.

        ' allow other filters 1st chance to modify the properties collection
        Dim ret As Boolean = BaseService.FilterProperties(component, properties)

        ' only remove properties if component is of type T
        If TypeOf component Is T AndAlso Not (properties.IsFixedSize Or properties.IsReadOnly) Then
            For Each propName As String In namesOfPropertiesToRemove
                ' If the IDictionary object does not contain an element with the specified key, 
                ' the IDictionary remains unchanged. No exception is thrown.
                properties.Remove(propName)
            Next
        End If
        Return ret
    End Function
End Class

表单中的示例用法:

Imports System.ComponentModel
Imports System.ComponentModel.Design

Public Class TestForm : Inherits Form
    Private host As IDesignerHost
    Private altTypeDescriptorProvider As FilterService(Of TestForm)

    ' spelling and character casing of removedPropertyNames is critical
    ' it is a case-sensative lookup
    Private Shared removedPropertyNames As String() = {"DoubleBuffered"}

    Public Overrides Property Site As ISite
        Get
            Return MyBase.Site
        End Get
        Set(value As ISite)
            If host IsNot Nothing Then
                UnwireDesignerCode()
            End If

            MyBase.Site = value
            If value IsNot Nothing Then
                host = CType(Site.GetService(GetType(IDesignerHost)), IDesignerHost)
                If host IsNot Nothing Then
                    If host.Loading Then
                        AddHandler host.LoadComplete, AddressOf HostLoaded
                    Else
                        WireUpDesignerCode()
                    End If
                End If
            End If
        End Set
    End Property

    Private Sub HostLoaded(sender As Object, e As EventArgs)
        RemoveHandler host.LoadComplete, AddressOf HostLoaded
        WireUpDesignerCode()
    End Sub

    Private Sub WireUpDesignerCode()
        AddFilter()
    End Sub

    Private Sub UnwireDesignerCode()
        If host IsNot Nothing Then
            RemoveFilter()
        End If
        host = Nothing
    End Sub

    Private Sub AddFilter()
        Dim baseFilter As ITypeDescriptorFilterService = CType(host.GetService(GetType(ITypeDescriptorFilterService)), ITypeDescriptorFilterService)
        If baseFilter IsNot Nothing Then
            ' remove existing filter service
            host.RemoveService(GetType(ITypeDescriptorFilterService))
            ' create our replacement service and add it to the host's services
            altTypeDescriptorProvider = New FilterService(Of TestForm)(baseFilter, removedPropertyNames)
            host.AddService(GetType(ITypeDescriptorFilterService), altTypeDescriptorProvider)
            TypeDescriptor.Refresh(Me.GetType) ' force a type description rescan 
        End If
    End Sub

    Private Sub RemoveFilter()
        If altTypeDescriptorProvider IsNot Nothing Then
            host.RemoveService(GetType(ITypeDescriptorFilterService))
            host.AddService(GetType(ITypeDescriptorFilterService), altTypeDescriptorProvider.BaseService)
            altTypeDescriptorProvider = Nothing
        End If
    End Sub
End Class

现在,当您创建一个继承自 的表单时TestForm,该DoubleBuffered属性将从 PropertyGrid 显示中排除。

在此处输入图像描述


推荐阅读