Hello All,
With regular properties, you can apply a TypeConverter to group related controls together in a TreeView manner (eg they display in the PropertyGrid with a plus sign that you can click to expand the list). This helps to organize related properties together regardless of property names.
I would like to do the same thing with Extender Provider properties but have not been able to figure out how to do so. I am assuming (I know, I know) that this is because Extender Provider properties are not really implemented as properties but as paired GetPropertyName/SetPropertyName methods.
A couple klugy work-a-rounds are possible: 1) Apply a Category attribute so that they are grouped together when viewed by Category or 2) use a common prefix to force them to be grouped together in the Property Grid. Neither of these options is desirable for obvious reasons.
Am I missing anything that would resolve this problem for me Thanks in advance!

Grouping Extender Provider properties in a Tree View manner
Kryor
If you would have any interest in beta testing my extended error provider, drop me an email at j2associates_NO_Spam@yahoo.com (minus the spam blocker).
Thanks again and have a great day!
LFDIII
I'm not sure I follow you. As an example, let's say I wanted to write an Extender Provider to add a boolean IsRequired property. The implementation of an Extender Provider requires that you use GetIsRequired and SetIsRequired as methods instead of properties. I'm not seeing how a separate class could be pulled into the Extender Provider to have it automatically be added to different controls (eg like a ToolTip). Thanks again for your response!
rzddr
So if you create a class that contains all your properties you can then simply return an instance of that class in your extended property, although you'll need a TypeConverter for the class in order to Serialize it. So you would end up with something like:
Public Class MyClass
...
public Property Prop1() As String
...
End Property
Public Property Prop2() As String
...
End Property
End Class
Public Class MyExtender
Implements IExtenderProvider
...
Public Sub SetMyGroupedProperty(target As Control, value As MyClass)
...
End Sub
Public Function GetMyGroupedProperty(target As Control) As MyClass
...
End Function
...
End Class
chanmy8
If you don't want it then simply remove the CanConvertFrom() and ConvertFrom() methods and return String.Empty in the ConvertTo() method if the destinationType is a string.
Kevin Kwan
Michael Hansen
You are close. Actually, I want to be able to group all of my extended properties in one place in a TreeView node style. That way they are all grouped together in one place in the PropertyGrid instead of being scattered throughout the list.
As an example, let's say I have a property IsRequired with an associated RequiredText property which allows me to specify the message which will be displayed by the ErrorProvider.
I can group them together in Category mode by applying the Category attribute to them, but what I really want is for them to be displayed under a Required node which would open up when clicked to display IsRequired and RequiredText, similarly to the way Location and Size work on a form. When you click Size, it opens up to display a Height and Width properties.
In your example above, where do you instantiate my class When I tried something similar, the properties did not show up in the various controls.
Thanks again for your responses!
Juan Jose Obregon
One additional thing is happening that I can't figure out. False is displayed next to the node + sign. Other times when I have used custom TypeConverters with a node view, I have overloaded or overwritten the ToString property to return String.Empty. That does not appear to work in this case, nor does reversing the property order so the string property is first. Any ideas and/or suggestions would be greatly appreciated.
NeilMaclean
Sorry for the slow reply, but I've been busy.
Any way, the following is a basic VB example showing my approach to this solution. The key to getting this working is in supplying a TypeConverter so that VS knows how to serialize the custom class.
Note that there is no error checking in this example.
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Reflection
<ProvideProperty("Required", GetType(Button))> _
Public Class TestExtender
Inherits System.ComponentModel.Component
Implements IExtenderProvider
#Region " Component Designer generated code "
'Standard Code cut for posting
#End Region
Public Function CanExtend(ByVal extendee As Object) As Boolean Implements System.ComponentModel.IExtenderProvider.CanExtend
Return TypeOf extendee Is Button
End Function
Private RequiredProps As New Hashtable
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public Sub SetRequired(ByVal target As Button, ByVal value As Requirements)
If RequiredProps.Contains(target) Then
RequiredProps.Remove(target)
End If
RequiredProps.Add(target, value)
End Sub
Public Function GetRequired(ByVal target As Button) As Requirements
If RequiredProps.Contains(target) Then
Return CType(RequiredProps(target), Requirements)
End If
RequiredProps.Add(target, New Requirements(False, String.Empty))
End Function
End Class
<TypeConverter(GetType(RequirementsConverter))> _
Public Class Requirements
Public Sub New(ByVal Reqd As Boolean, ByVal ReqdTxt As String)
MyBase.new()
m_IsRequired = Reqd
m_RequiredText = ReqdTxt
End Sub
Private m_IsRequired As Boolean
Private m_RequiredText As String
Public Property IsRequired() As Boolean
Get
Return m_IsRequired
End Get
Set(ByVal Value As Boolean)
m_IsRequired = Value
End Set
End Property
Public Property RequiredText() As String
Get
Return m_RequiredText
End Get
Set(ByVal Value As String)
m_RequiredText = Value
End Set
End Property
End Class
Public Class RequirementsConverter
Inherits ExpandableObjectConverter
Public Overloads Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
Return destinationType Is GetType(InstanceDescriptor) OrElse _
destinationType Is GetType(String)
End Function
Public Overloads Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
Dim req As Requirements = CType(value, Requirements)
If destinationType Is GetType(String) Then
Dim returnString As String = req.IsRequired.ToString
If req.RequiredText.Length > 0 Then
returnString += "," & req.RequiredText
End If
Return returnString
ElseIf destinationType Is GetType(InstanceDescriptor) Then
Dim ci As ConstructorInfo = GetType(Requirements).GetConstructor(New Type() {GetType(Boolean), GetType(String)})
Return New InstanceDescriptor(ci, New Object() {req.IsRequired, req.RequiredText})
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
Public Overloads Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
Return sourceType Is GetType(String)
End Function
Public Overloads Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
Dim str() As String = CType(value, String).Split(","c)
Return New Requirements(str(0) = Boolean.TrueString, str(1))
End Function
End Class