2014-12-09 27 views
0

情景在屬性網格中創建可展開的組?

我有子類的時候,我控制啓用殘疾人,或只讀模式ListBox和我添加顏色屬性:

enter image description here

問題

在C#或VB.Net,我需要做的,在屬性網格中的屬性組織成這種結構?:

[+] State Enabled 

    [+] Selected Item 
     · BackColor 
     · ForeColor 

    [+] Unselected Item 
     · BackColor 
     · ForeColor 

這是從Krypton LIB採取了視覺例子擴張組演示我想什麼用戶控件模仿:

enter image description here

UPDATE

我認爲,在這個網址進行了說明所有必要的有關財產電網:

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

這不是簡單的化妝品。首先,它依賴於一個類型,你可能會將它們定義爲顏色。其次,如果Type是一個標準類型,比如Size或Point,VS會自動執行它(定義一個新的道具'FooBar As Point'並參見)。否則,您可能需要編寫自己的UITypeEditor和/或TypeConverter。 (請注意鏈接文章中的所有標準類型:位置,字體大小)。有時,您可以在TypeConverter中提供足夠的信息以使其自動工作。 – Plutonix 2014-12-09 14:06:22

回答

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 

Property Window

設計文件

Me.UiListBox1.StateDisabled.Background.Selected = System.Drawing.Color.Red 
+0

Thankyou的例子,但我不明白如何使用它,我怎麼可以在運行時更新值?例如我不能這樣做:'UiListBox1.StateEnabled.Background.Selected = Color.Black',我不理解如何以這種方式實現'Setter',另外,當屬性更新時,我應該使控制(我正在從上面提供的代碼示例中的'Setter'中這樣做),但是從這些類我無法訪問基類來使其無效,請您擴展該示例嗎? – ElektroStudios 2014-12-09 16:01:37

+0

這就是我與任何結果嘗試:'公共財產StateEnabled()作爲ItemLayout 獲取 返回Me.m_stateEnabled 最終獲取 套裝(價值作爲ItemLayout) Me.m_stateEnabled =值 MyBase.Invalidate MyBase。 Visible = False'試圖設置一個隨機控件的屬性 End Set End Property' – ElektroStudios 2014-12-09 16:07:25

+0

@ElektroStudios我更新了代碼。 – 2014-12-09 16:21:44

1

是否[Category]屬性的工作是什麼?

Example

+0

謝謝但類別屬性僅適用於屬性按類別(分類)排序,而不是在屬性網格中按字母順序排序時。 – ElektroStudios 2014-12-09 12:37:18

+0

你提供的例子解釋了一個與你的建議完全不同的東西,看起來很難實現這樣的事情,在我看來,似乎並沒有我分享過的氪的圖像我的問題使用集合數據來創建組,因爲它沒有提供任何按鈕來編輯集合內容,例如您提供的示例的圖5,然後我真的希望它可以更容易地完成。感謝您的回答。 – ElektroStudios 2014-12-09 12:38:02

2

一個TypeConverter並不那麼可怕,因爲它聽起來:首先,列表框屬性聲明:

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 

下一個定義​​類:

<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能力和屬性網格(S)翻譯的內容顯示:

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允許您控制當財產被摺疊顯示的內容:

enter image description here


上述功能之一的TypeConverter,通常執行是序列化代碼/ DES爲設計師排列你的類型。這裏不需要,因爲Type只是Color,VS/NET知道該怎麼做。它所做的在這種情況下做的是:
- 標記的財產擴展
- 提供當財產被摺疊的「摘要」信息

你會需要它的另一件事是,當你嵌入一個類型另一個(如在myControl.StateEnabled.SelectedItem.ForeColor)。通過將它們嵌套在一起,你將需要一個TypeConverter或者一些代碼解決方案,例如一個實例引用(並且我永遠無法知道你的問題的哪些元素是必備的)。 VS只知道鑽入第一層,您將不得不提供TypeConverter深入查看顏色數據。然而,SelectedItem,DeselectedItemReadOnlyItem都可以使用相同的TypeConverter

enter image description here

foo的類型不同於組分繼承,也向下提供一個空的下降。

參見:

ExpandableObjectConverter
How to: Implement a Type Converter


最後一點:所有的道具二傳手應該測試傳遞的價值和拒絕Color.Transparent

+0

我看到這個答案太晚了,我會試試看,謝謝! – ElektroStudios 2014-12-09 16:33:15

+0

我不知道如果你可以解釋你如何在圖像中添加「SelectedItemColor」到「Electro」組中,我無法看到如何做到這一點 – ElektroStudios 2014-12-09 16:44:07