SCENARIO
我已对ListBox
进行了细分,并且当我的控件已启用,已禁用或时,我添加了颜色属性ReadOnly 模式:
问题
在C#或VB.Net中,我需要做什么才能将属性网格中的属性组织成具有此结构的可扩展组?:
[+] State Enabled
[+] Selected Item
· BackColor
· ForeColor
[+] Unselected Item
· BackColor
· ForeColor
这是一个从Krypton
lib用户控件中获取的可视示例,它演示了我想要模仿的内容:
更新
我认为在这个网址中解释了所有关于财产网格的必要条件:
http://www.codeproject.com/Articles/2764/Using-PropertyGrid-Part-I
但它专注于使用具有加载事件的表单来执行此操作,我仍然无法理解如何在我的用户控件中实现该示例,因为如果我创建一个子类来自定义像那个例子中的属性网格,然后我无法访问我的控件的基类。
我的代码有一个简单的结构:
Public Class ElektroListBox : Inherits ListBox
<Category("Appearance")>
<Description("The BackColor to paint the selected item when the control is enabled.")>
Public Property StateEnabledItemSelectedBackColor As Color
Get
Return Me.stateEnabledItemSelectedBackColor1
End Get
Set(ByVal value As Color)
Me.stateEnabledItemSelectedBackColor1 = value
Me.Invalidate(invalidateChildren:=False)
End Set
End Property
Private stateEnabledItemSelectedBackColor1 As Color = Color.Red
End Class
答案 0 :(得分:3)
TypeConverter
并不像听起来那么可怕:首先,ListBox属性声明:
Public Class ListBoxEx
Inherits ListBox
<Browsable(True), EditorBrowsable(EditorBrowsableState.Always),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Property SelectedItemColor As ItemStateColors
<Browsable(True), EditorBrowsable(EditorBrowsableState.Always),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
DefaultValue(-1)>
Public Property UnSelectedItemColor As ItemStateColors
Public Sub New()
' they are Objects, be sure to instance them!
' VERY important!
SelectedItemColor = New ItemStateColors
UnSelectedItemColor = New ItemStateColors
End Sub
end class
接下来定义您的ItemStateColors
班级:
<TypeConverter(GetType(ItemStateConverter))>
Public Class ItemStateColors
<Browsable(True), NotifyParentProperty(True),
EditorBrowsable(EditorBrowsableState.Always), DefaultValue(GetType(Color), "")>
Public Property EnabledBackColor As Color
<Browsable(True), NotifyParentProperty(True),
EditorBrowsable(EditorBrowsableState.Always), DefaultValue(GetType(Color), "")>
Public Property DisabledBackColor As Color
Public Sub New()
' default values, if any
EnabledBackColor = SystemColors.Window
DisabledBackColor = SystemColors.Control
End Sub
End Class
您的每个ItemState
属性都是此类的一个实例。请注意,Type
包含TypeConverter
属性 - 这提供了“魔力”。我们将提供expando功能并转换内容以在属性网格中显示:
Public Class ItemStateConverter
Inherits ExpandableObjectConverter
Public Overrides Function ConvertTo(context As ITypeDescriptorContext,
culture As Globalization.CultureInfo,
value As Object, destinationType As Type) As Object
If destinationType Is GetType(String) Then
Dim item As ItemStateColors = CType(value, ItemStateColors)
' ToDo: decide the format of collapsed info
Return String.Format("{0}, {1}", item.EnabledBackColor.ToString,
item.DisabledBackColor.ToString)
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
Component
方法更容易实现,但TypeConverter
允许您控制属性折叠时显示的内容:
TypeConverter 通常执行的功能之一是为设计器序列化/反序列化类型的代码。这里不需要这样,因为Type只是Color
,VS / NET知道怎么做。它在这种情况下做的是:
- 将该属性标记为可扩展
- 在财产崩溃时提供“摘要”信息
您需要的另一件事是将一种类型嵌入另一种类型(如myControl.StateEnabled.SelectedItem.ForeColor
)。通过嵌套它们,您将需要TypeConverter
或某些代码解决方案,例如实例引用(我永远无法分辨您的问题的哪些元素是必须的)。 VS只知道钻入第一层,你必须提供TypeConverter
来深入挖掘以获取颜色数据。但是,SelectedItem
,DeselectedItem
和ReadOnlyItem
都可以使用相同的TypeConverter
。
继承自Component的Foo Type也提供空下拉。
另见:
ExpandableObjectConverter
How to: Implement a Type Converter
最后注意事项:您的所有Prop Setters都应该测试传递的值并拒绝Color.Transparent
。
答案 1 :(得分:1)
[Category]
属性是否适用于此?
答案 2 :(得分:1)
您需要做的第一件事是将属性结构化为类。然后,您需要为每个类创建一个自定义type converter,以便它可以序列化。但是,有一种更简单的方法来实现这一目标;继承Component类。这是一个简单的例子。
Public Class UIListBox
Inherits ListBox
Public Sub New()
Me.m_stateDisabled = New ItemLayout(Me)
Me.m_stateEnabled = New ItemLayout(Me)
Me.m_stateReadOnly = New ItemLayout(Me)
End Sub
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public ReadOnly Property StateDisabled() As ItemLayout
Get
Return Me.m_stateDisabled
End Get
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public ReadOnly Property StateEnabled() As ItemLayout
Get
Return Me.m_stateEnabled
End Get
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public ReadOnly Property StateReadOnly() As ItemLayout
Get
Return Me.m_stateReadOnly
End Get
End Property
Friend Sub NotifyStateChanged(source As ItemLayoutColors, propertyName As String)
Me.Invalidate()
Debug.WriteLine("UIListBox: State changed.")
End Sub
Private m_stateDisabled As ItemLayout
Private m_stateEnabled As ItemLayout
Private m_stateReadOnly As ItemLayout
End Class
<ToolboxItem(False)>
Public Class ItemLayout
Inherits Component
Public Sub New(listBox As UIListBox)
Me.m_listBox = listBox
Me.m_background = New ItemLayoutColors(Me)
Me.m_foreground = New ItemLayoutColors(Me)
End Sub
Friend ReadOnly Property ListBox() As UIListBox
Get
Return Me.m_listBox
End Get
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public ReadOnly Property Background() As ItemLayoutColors
Get
Return Me.m_background
End Get
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public ReadOnly Property Foreground() As ItemLayoutColors
Get
Return Me.m_foreground
End Get
End Property
Private m_background As ItemLayoutColors
Private m_foreground As ItemLayoutColors
Private m_listBox As UIListBox
End Class
<ToolboxItem(False)>
Public Class ItemLayoutColors
Inherits Component
Public Sub New(layout As ItemLayout)
If (layout Is Nothing) Then Throw New ArgumentNullException("layout")
Me.m_layout = layout
End Sub
Friend ReadOnly Property Layout() As ItemLayout
Get
Return Me.m_layout
End Get
End Property
Public Property Selected() As Color
Get
Return Me.m_selected
End Get
Set(value As Color)
If (value <> Me.m_selected) Then
Me.m_selected = value
Me.Layout.ListBox.NotifyStateChanged(Me, "Selected")
End If
End Set
End Property
Public Property Unselected() As Color
Get
Return Me.m_unselected
End Get
Set(value As Color)
If (value <> Me.m_unselected) Then
Me.m_unselected = value
Me.Layout.ListBox.NotifyStateChanged(Me, "Unselected")
End If
End Set
End Property
Private Function ShouldSerializeSelected() As Boolean
Return (Me.Selected <> Color.Empty)
End Function
Private Function ShouldSerializeUnselected() As Boolean
Return (Me.Unselected <> Color.Empty)
End Function
Private m_selected As Color
Private m_unselected As Color
Private m_layout As ItemLayout
End Class
设计师档案
Me.UiListBox1.StateDisabled.Background.Selected = System.Drawing.Color.Red