我的Property
上有一个User Control
,它像这样隐藏在设计模式下
<Browsable(False)>
Public Property MyProperty As Object
我要根据另一个True
的值将其更改为Property
。
类似
Private _otherProperty As Boolean
Public Property OtherProperty() As Boolean
Get
Return _otherProperty
End Get
Set(ByVal value As Boolean)
_otherProperty = value
If value = True Then
'Set MyProperty Browsable Attribute True here
Else
'Set MyProperty Browsable Attribute False here
End If
End Set
End Property
这就是我的想法。
基本上,我希望Property
仅在另一个Property
设置为True
时在设计时可用,但找不到在设计模式下更改属性值的方法。
答案 0 :(得分:1)
通过PropertyDescriptors管理WinForm设计器的PropertyGrid中显示的属性。您可以通过两种不同的方式控制检查机制返回的描述符。一种相对简单(虽然乏味)的方法是让您的类实现ICustomTypeDescriptor Interface。
让我们假设您的usercontrol类定义如下:
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
请注意RefreshPropertiesAttribute装饰OtherProperty
。这将告诉PropertyGrid每次此属性更改时都拉动所有属性。这是必需的,以便在MyProperty
为真时显示OtherProperty
属性的逻辑起作用。
在另一个类文件中,添加以下实现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
大多数实现只返回基础TypeDescriptor
所提供的内容。在GetProperties
函数中,实现了用可浏览的逻辑替换MyProperty
属性的不可浏览的PropertyDescriptor的逻辑。
一旦这是代码被编译,DemoUC
控件将在PropertyGrid中这样显示。请注意,根据MyProperty
的值显示/隐藏了OtherProperty
。
答案 1 :(得分:0)
自ControlDesigner派生的与用户控件相关联的定制设计器上的besing实现。
覆盖ControlDesigner
PostFilterProperties方法,我们可以从方法引用的IDictionary
属性中删除现有属性:
Dim propDescriptor = DirectCast(properties("PropertyName"), PropertyDescriptor)
properties.Remove("PropertyName");
覆盖PreFilterProperties方法,可以使用PropertyDescriptor来添加属性(如果先前已删除该属性,则添加回来):
properties.Add("PropertyName", propDescriptor)
可以在由另一个属性的值设置的条件下删除该属性,还可以验证DesignMode
(或UserControl
)的Control
状态:
If (Not (Me.Control.Site.DesignMode) OrElse DirectCast(Me.Control, MyUserControl).SomeProperty) Then
'(...)
End If
引起属性集合更改的属性必须用装饰,并设置为RefreshProperties.All。
<RefreshProperties(RefreshProperties.All)>
Public Property MyPropertyA As Boolean = True
示例行为:
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
<Designer(GetType(MyUserControlDesigner))>
Partial Public Class MyUserControl
Inherits UserControl
<RefreshProperties(RefreshProperties.All)>
Public Property MyPropertyA As Boolean = True
Public Property MyPropertyB As Boolean
End Class
<DebuggerDisplay("MyUserControlDesigner", Name:="MyUserControlDesigner")>
Public Class MyUserControlDesigner
Inherits ControlDesigner
Private propDescriptor As PropertyDescriptor = Nothing
Protected Overrides Sub PreFilterProperties(properties As System.Collections.IDictionary)
MyBase.PreFilterProperties(properties)
If Not Me.Control.Site.DesignMode OrElse DirectCast(Me.Control, MyUserControl).MyPropertyA Then
If Not properties.Contains("MyPropertyB") Then
properties.Add("MyPropertyB", propDescriptor)
End If
End If
End Sub
Protected Overrides Sub PostFilterProperties(properties As System.Collections.IDictionary)
If Me.Control.Site.DesignMode AndAlso Not DirectCast(Me.Control, MyUserControl).MyPropertyA Then
If properties.Contains("MyPropertyB") Then
propDescriptor = DirectCast(properties("MyPropertyB"), PropertyDescriptor)
properties.Remove("MyPropertyB")
End If
End If
MyBase.PostFilterProperties(properties)
End Sub
End Class