Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I have a custom control that makes use of four different images. These images are stored as Assets under the various 'themes', such that the 'Star Theme' which will have four images based on star shapes.

The control has a Theme property, but I would like to extend the concept so that user defined Themes can be created.

I hope to add 'UserDefined' to my Themes enumeration and if this option is selected from the property page then I would like to display four new properties from where the four user defined image sources can be set.

Any ideas?
Posted

For this you have to implement the ICustomTypeDescriptor and you have to create a new PropertyDescriptor with gives the Property (Properties) the Attribute BrowsableAttribute.No.

It is a Little bit complicated to do that.
I give you an example and in case of trouble you should reply ...

At first the class and the Property :
VB
Imports System.ComponentModel

Public Class RMBaseLed
    Inherits System.Windows.Forms.Control
    Implements ICustomTypeDescriptor

' my Enum
    Enum DarstellungAnzeige
        Test
        Rund
        Eckig
        AreaSunken
        AreaRaised
    End Enum

    <refreshproperties(refreshproperties.all)>
    Property Darstellung As DarstellungAnzeige
        Get
            Return my_Darstellung
        End Get
        Set(ByVal value As DarstellungAnzeige)
            my_Darstellung = value
            Me.Invalidate()
        End Set
    End Property

    Private my_Darstellung As DarstellungAnzeige = DarstellungAnzeige.Rund

end class


now the code inside the class which represents the ICustomTypeDescriptor and additional code :
VB
    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes
        Return TypeDescriptor.GetAttributes(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName
        Return TypeDescriptor.GetClassName(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetComponentNaMe() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName
        Return TypeDescriptor.GetComponentName(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetConverter() As System.ComponentModel.TypeConverter _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter
        Return TypeDescriptor.GetConverter(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent
        Return TypeDescriptor.GetDefaultEvent(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty
        Return TypeDescriptor.GetDefaultProperty(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Function GetEditor(ByVal editorBaseType As System.Type) As Object _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor
        Return TypeDescriptor.GetEditor(Me, editorBaseType, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Overloads Function GetEvents() As System.ComponentModel.EventDescriptorCollection _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return TypeDescriptor.GetEvents(Me, True)
    End Function

    <Description("Simply delegates to the TypeDescriptor method.")> _
    Public Overloads Function GetEvents(ByVal attributes() As System.Attribute) As System.ComponentModel.EventDescriptorCollection _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return TypeDescriptor.GetEvents(Me, attributes, True)
    End Function

    <Description("Returns the wrapped object.")> _
    Public Function GetPropertyOwner(ByVal pd As System.ComponentModel.PropertyDescriptor) As Object _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner
        Return Me
    End Function

    <Description("Returns the list of properties as defined in the constructor")> _
    Public Overloads Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        Dim pd As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, True)
        Return FilterProperties(pd)
    End Function

    <Description("Returns the list of properties as defined in the constructor")> _
    Public Overloads Function GetProperties(ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection _
           Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        Dim pd As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, attributes, True)
        Return FilterProperties(pd)
    End Function



    
    Private Function FilterProperties(ByVal origProperties As PropertyDescriptorCollection) As PropertyDescriptorCollection

        Dim myPD As PropertyDescriptor
        Dim myListe As New ArrayList
        Dim setHidden As Boolean

        For i As Integer = 0 To origProperties.Count - 1
            myPD = origProperties.Item(i)
            setHidden = False

' depending on the selection of the Enum I make the following Properties visible / unvisible
            Select Case myPD.Name
                Case "ForeColor"
                    If Darstellung <> DarstellungAnzeige.Rund _
                    And Darstellung <> DarstellungAnzeige.Eckig Then setHidden = True
                Case "Size"
                    If Darstellung = DarstellungAnzeige.Rund Then setHidden = True
                Case "Diameter"
                    If Darstellung <> DarstellungAnzeige.Rund Then setHidden = True
            End Select

            If setHidden Then
                myListe.Add(New HiddenPropertyDescriptor(myPD))
            Else
                myListe.Add(myPD)
            End If
        Next

        Dim myPDListe(myListe.Count - 1) As PropertyDescriptor
        myListe.CopyTo(myPDListe)
        Return New PropertyDescriptorCollection(myPDListe)
    End Function


at last the "HiddenPropertyDescriptor" :
VB
Imports System.ComponentModel

Friend NotInheritable Class HiddenPropertyDescriptor
    Inherits PropertyDescriptor
    Private myPD As PropertyDescriptor = Nothing

    Public Sub New(ByVal pd As PropertyDescriptor)
        MyBase.New(pd)
        myPD = pd
    End Sub

    Public Overrides ReadOnly Property Attributes() As AttributeCollection
        Get
            Return New AttributeCollection(BrowsableAttribute.No)
            'Return myPD.Attributes
        End Get
    End Property

    Protected Overrides Sub FillAttributes(ByVal attributeList As IList)
        attributeList.Add(BrowsableAttribute.No)
    End Sub

    Public Overrides ReadOnly Property IsBrowsable As Boolean
        Get
            Return False
            'Return myPD.IsBrowsable
        End Get
    End Property

    Public Overrides ReadOnly Property ComponentType() As Type
        Get
            Return myPD.ComponentType
        End Get
    End Property

    ' The type converter for this property.
    ' A translator can overwrite with its own converter.
    Public Overrides ReadOnly Property Converter() As TypeConverter
        Get
            Return myPD.Converter
        End Get
    End Property

    ' Returns the property editor 
    ' A translator can overwrite with its own editor.
    Public Overrides Function GetEditor(ByVal editorBaseType As Type) As Object
        Return Me.myPD.GetEditor(editorBaseType)
    End Function

    ' Specifies the property is read only.
    Public Overrides ReadOnly Property IsReadOnly() As Boolean
        Get
            Return myPD.IsReadOnly
        End Get
    End Property

    Public Overrides ReadOnly Property PropertyType() As Type
        Get
            Return myPD.PropertyType
        End Get
    End Property

    Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
        Return myPD.CanResetValue(component)
    End Function

    Public Overrides Function GetValue(ByVal component As Object) As Object
        Return myPD.GetValue(component)
    End Function

    Public Overrides Sub ResetValue(ByVal component As Object)
        myPD.ResetValue(component)
    End Sub

    Public Overrides Sub SetValue(ByVal component As Object, ByVal val As Object)
        myPD.SetValue(component, val)
    End Sub

    ' Determines whether a value should be serialized.
    Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
        Return myPD.ShouldSerializeValue(component)
    End Function

End Class


good luck ...
 
Share this answer
 
v3
Interesting, but I'm using Windows Phone 8 and can't find ICustomTypeDescriptor or the refreshproperties attribute :( Any suggestions ?
 
Share this answer
 
Comments
Ralf Meier 31-Jul-15 17:11pm    
Don't use an answer as reply.

What do you think that you try to achieve ?
The functionality of the control has nothing to do with the device on which it is working later.
I supposed that we speak about the development system. About what do you speak ? To where should your question point ?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900