This topic explains how the control identifies and displays expandable properties.
The following topics are prerequisites to understanding this topic:
This topic contains the following sections:
The xamPropertyGrid control supports the displaying of "expandable" properties. These properties contain child items/elements which can be revealed by clicking the expander glyph at the left edge of the expandable property item. A property is considered to be expandable if it satisfies certain criteria which are discussed below.
Types With Public Properties - types which exposes one or more public properties (for example the Style
property of a Button
instance) or which have an ExpandableObjectConverter
attribute. When expanded, the xamPropertyGrid displays an indented list of the type’s properties.
If the type has a public parameter-less constructor and the property value is currently null, the xamPropertyGrid will display a button with a plus sign at the right edge of the property item which, when clicked, will create an instance of the type.
The following screenshot shows a type with public properties (ContextMenu) rendered in the xamPropertyGrid :
Collection Types - types which implement ICollection
, IList
or IEnumerable
. When expanded, the xamPropertyGrid displays an indented list of the elements in the list.
If the list is an ICollection<T>
where T
has a public parameter-less constructor, and the list is modifiable, the xamPropertyGrid will display a button with a plus sign at the right edge of the list property which, when clicked, will add an entry of type T
to the list.
If the list is modifiable, the xamPropertyGrid will also display a button with a minus sign at the right edge of each list element which, when clicked, will remove the respective element from the list.
The following screenshot shows a list type property (ColumnDefinitions) rendered in the xamPropertyGrid :
Expand/collapse handle for an expandable property/collection
Properties/elements of the expandable property/collection
Plus-button for adding more elements to this collection
Minus-buttons for removing particular element from this collection
By default the xamPropertyGrid control renders the collection type and the elements count in the value column. You can modify this value by performing the following steps:
Create a class deriving from System.ComponentModel.TypeConverter
Override the ConvertTo
method to return the desired string value
Decorate your collection property with the TypeConverter
attribute and provide as argument the type of the class created in the first step
The following screenshot shows the default collection rendering on the left and a collection with customized rendering on the right:
The following code snippet shows how to achieve the above result:
In Visual Basic:
Public Class CustomTypeConverter
Inherits TypeConverter
Public Overrides Function ConvertTo( _
context As ITypeDescriptorContext, _
culture As CultureInfo, _
value As [Object], _
destinationType As Type) As Object
Return "Employee's Collection"
End Function
End Class
…
<TypeConverter(GetType(CustomTypeConverter))> _
Public Property Customers() As List(Of Customer)
Get
Return m_Customers
End Get
Set
m_Customers = Value
End Set
End Property
Private m_Customers As List(Of Customer)
In C#:
public class CustomTypeConverter : TypeConverter
{
public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture,
Object value,
Type destinationType)
{
return "Employee's Collection";
}
}
…
[TypeConverter(typeof(CustomTypeConverter))]
public List<Customer> Customers
{
get; set;
}
By default the xamPropertyGrid control renders the collection’s elements as indexes in square brackets ([0], [1], [2]…). You can customize this by performing the following steps:
Have your collection implement the System.ComponentModel.ICustomTypeDescriptor
interface.
The key method to implement from this interface is the GetProperties()
method. It should return a collection of objects which should be extending from the System.ComponentModel.PropertyDescriptor
type.
Provide a custom display name for each collection’s element by overriding the PropertyDescriptor’s
DisplayName
string property.
The following screenshot shows the default collection element’s rendering on the left and a collection with customized element’s rendering on the right:
The following code snippet shows how to achieve the above result:
In Visual Basic:
Public Class Employee
Public Property FirstName() As String
Get
Return m_FirstName
End Get
Set
m_FirstName = Value
End Set
End Property
Private m_FirstName As String
Public Property LastName() As String
Get
Return m_LastName
End Get
Set
m_LastName = Value
End Set
End Property
Private m_LastName As String
End Class
Public Class EmployeePropertyDescriptor
Inherits PropertyDescriptor
Private collection As EmployeeCollection
Private index As Integer
Public Sub New(col As EmployeeCollection, i As Integer)
Me.collection = col
Me.index = i
End Sub
Public Overrides ReadOnly Property DisplayName() As String
Get
Dim emp As Employee = Me.collection(index)
Return emp.FirstName & " " & Convert.ToString(emp.LeftName)
End Get
End Property
End Class
Public Class EmployeeCollection
Inherits List(Of Employee)
Implements ICustomTypeDescriptor
Public Function GetProperties() As PropertyDescriptorCollection
Dim pds As New PropertyDescriptorCollection(Nothing)
For i As Integer = 0 To Me.Count - 1
Dim pd As New EmployeePropertyDescriptor(Me, i)
pds.Add(pd)
Next
Return pds
End Function
End Class
In C#:
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class EmployeePropertyDescriptor : PropertyDescriptor
{
private EmployeeCollection collection;
private int index;
public EmployeePropertyDescriptor(EmployeeCollection col, int i)
{
this.collection = col;
this.index = i;
}
public override string DisplayName
{
get
{
Employee emp = this.collection[index];
return emp.FirstName + " " + emp.LeftName;
}
}
}
public class EmployeeCollection : List<Employee>, ICustomTypeDescriptor
{
public PropertyDescriptorCollection GetProperties()
{
PropertyDescriptorCollection pds = new PropertyDescriptorCollection(null);
for (int i = 0; i < this.Count; i++)
{
EmployeePropertyDescriptor pd = new EmployeePropertyDescriptor(this, i);
pds.Add(pd);
}
return pds;
}
}
You can provide external editors for both collection types and types with public properties. By providing such external editors the xamPropertyGrid will not render the indented list of properties/collection items. Instead the supplied external editor will be used to rendering the expandable property and/or collection’s data.
When creating your external editor’s data template keep in mind that the data template’s data context will be set to the PropertyGridPropertyItem associated with the expandable property which means you can obtain the underlying property value by binding to the PropertyGridPropertyItem’s
Value property.
For more information on how to provide external editors see the Configuring Editors Definitions topic.
The following topics provide additional information related to this topic.