The properties displayed in the WinForm designer's PropertyGrid are managed via PropertyDescriptors. You can control the descriptors returned by the inspection mechanisms by a couple of different ways. A relatively simple (while tedious) way is have your class implement the ICustomTypeDescriptor Interface.
Let us assume your usercontrol class is defined as follows:
Imports System.ComponentModel
Public Class DemoUC
Public Sub New()
InitializeComponent()
End Sub
<RefreshProperties(RefreshProperties.All)>
Public Property OtherProperty As Boolean
<Browsable(False)>
Public Property MyProperty As String
End Class
Notice the RefreshPropertiesAttribute decorating OtherProperty
. This will tell the PropertyGrid to pull all properties each time this property changes. This is needed so that logic to display the MyProperty
property when OtherProperty
is true will work.
In another class file, add the following partial class that implements the ICustomTypeDescriptor Interface
.
Imports System.ComponentModel
Partial Public Class DemoUC : Implements ICustomTypeDescriptor
Public Function GetAttributes() As AttributeCollection Implements ICustomTypeDescriptor.GetAttributes
Return TypeDescriptor.GetAttributes(Me, True)
End Function
Public Function GetClassName() As String Implements ICustomTypeDescriptor.GetClassName
Return TypeDescriptor.GetClassName(Me, True)
End Function
Public Function GetComponentName() As String Implements ICustomTypeDescriptor.GetComponentName
Return TypeDescriptor.GetComponentName(Me, True)
End Function
Public Function GetConverter() As TypeConverter Implements ICustomTypeDescriptor.GetConverter
Return TypeDescriptor.GetConverter(Me, True)
End Function
Public Function GetDefaultEvent() As EventDescriptor Implements ICustomTypeDescriptor.GetDefaultEvent
Return TypeDescriptor.GetDefaultEvent(Me, True)
End Function
Public Function GetDefaultProperty() As PropertyDescriptor Implements ICustomTypeDescriptor.GetDefaultProperty
Return TypeDescriptor.GetDefaultProperty(Me, True)
End Function
Public Function GetEditor(editorBaseType As Type) As Object Implements ICustomTypeDescriptor.GetEditor
Return TypeDescriptor.GetEditor(Me, editorBaseType, True)
End Function
Public Function GetEvents() As EventDescriptorCollection Implements ICustomTypeDescriptor.GetEvents
Return TypeDescriptor.GetEvents(Me, True)
End Function
Public Function GetEvents(attributes() As Attribute) As EventDescriptorCollection Implements ICustomTypeDescriptor.GetEvents
Return TypeDescriptor.GetEvents(Me, attributes, True)
End Function
Public Function GetProperties() As PropertyDescriptorCollection Implements ICustomTypeDescriptor.GetProperties
Return GetProperties({})
End Function
Public Function GetProperties(attributes() As Attribute) As PropertyDescriptorCollection Implements ICustomTypeDescriptor.GetProperties
Dim basePDs As New PropertyDescriptorCollection(Nothing, False)
For Each pd As PropertyDescriptor In TypeDescriptor.GetProperties(Me, attributes, True)
basePDs.Add(pd)
Next
If Me.DesignMode AndAlso Me.OtherProperty Then
Dim pd As PropertyDescriptor = TypeDescriptor.GetProperties(Me, True).Cast(Of PropertyDescriptor).Where(Function(desc As PropertyDescriptor) desc.Name.Equals(NameOf(Me.MyProperty))).FirstOrDefault()
If basePDs.Contains(pd) Then
basePDs.Remove(pd)
End If
basePDs.Add(New BrowsableDescriptor(pd))
End If
Return basePDs
End Function
Public Function GetPropertyOwner(pd As PropertyDescriptor) As Object Implements ICustomTypeDescriptor.GetPropertyOwner
Return Me
End Function
Class BrowsableDescriptor : Inherits PropertyDescriptor
Private src As PropertyDescriptor
Public Sub New(src As PropertyDescriptor)
MyBase.New(src.Name, Nothing)
Me.src = src
Dim attribs As New List(Of Attribute)
For Each att As Attribute In src.Attributes
If TypeOf att Is BrowsableAttribute Then Continue For
attribs.Add(att)
Next
attribs.Add(BrowsableAttribute.Yes)
MyBase.AttributeArray = attribs.ToArray
End Sub
Public Overrides ReadOnly Property IsBrowsable As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property ComponentType As Type
Get
Return src.ComponentType
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return src.IsReadOnly
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return src.PropertyType
End Get
End Property
Public Overrides Sub ResetValue(component As Object)
src.ResetValue(component)
End Sub
Public Overrides Sub SetValue(component As Object, value As Object)
src.SetValue(component, value)
End Sub
Public Overrides Function CanResetValue(component As Object) As Boolean
Return src.CanResetValue(component)
End Function
Public Overrides Function GetValue(component As Object) As Object
Return src.GetValue(component)
End Function
Public Overrides Function ShouldSerializeValue(component As Object) As Boolean
Return src.ShouldSerializeValue(component)
End Function
End Class
End Class
The majority of the implementation just returns what the base TypeDescriptor
would provide. The GetProperties
function is where the logic is implemented to replace the non-browsable PropertyDescriptor for the MyProperty
property with a browsable one takes place.
Once this is code is compiled, the DemoUC
control will display like this in the PropertyGrid. Observe that MyProperty
is shown/Hidden based on the value of OtherProperty
.
