How to order properties in RadDataEntry
Environment
Product Version | 2018.1 220 |
Product | RadDataEntry for WinForms |
Description
By default, RadDataEntry generates the editors for the fields ordered in the way they are defined in the DataSource object. A common scenario is to change the fields' order according to certain criteria.
Solution
Consider you have a class Person as follows:
Define Person class
public class Person
{
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime BirthDate { get; set; }
public int Id { get; set; }
public string Address { get; set; }
public Person(string lastName, string firstName, DateTime dateOfBirth, int id, string address)
{
this.LastName = lastName;
this.FirstName = firstName;
this.BirthDate = dateOfBirth;
this.Id = id;
this.Address = address;
}
}
Public Class Person
Public Property LastName As String
Public Property FirstName As String
Public Property BirthDate As DateTime
Public Property Id As Integer
Public Property Address As String
Public Sub New(ByVal lastName As String, ByVal firstName As String, ByVal dateOfBirth As DateTime, ByVal id As Integer, ByVal address As String)
Me.LastName = lastName
Me.FirstName = firstName
Me.BirthDate = dateOfBirth
Me.Id = id
Me.Address = address
End Sub
End Class
Then, set the RadDataEntry.DataSource property:
Set DataSource
this.radDataEntry1.DataSource = new List<Person> { new Person("Smith", "John", new DateTime(1980, 1, 1), 12345, "452 Holly Lane Hopewell, VA 23860") };
Me.radDataEntry1.DataSource = New List(Of Person) From {
New Person("Smith", "John", New DateTime(1980, 1, 1), 12345, "452 Holly Lane Hopewell, VA 23860")
}
In the below screenshot it is demonstrated how the properties are displayed - in the order they are defined in the Person class:
Now, we will change the properties' order.
1. For this purpose, we will use the RadSortOrderAttribute which is available in the Telerik.WinControls.UI namespace. Thus, each property will have a specific number indicating the sort order.
public class OrderedPerson
{
[RadSortOrder(3)]
public string LastName { get; set; }
[RadSortOrder(2)]
public string FirstName { get; set; }
[RadSortOrder(4)]
public DateTime BirthDate { get; set; }
[RadSortOrder(1)]
public int Id { get; set; }
[RadSortOrder(5)]
public string Address { get; set; }
public OrderedPerson(string lastName, string firstName, DateTime dateOfBirth, int id, string address)
{
this.LastName = lastName;
this.FirstName = firstName;
this.BirthDate = dateOfBirth;
this.Id = id;
this.Address = address;
}
}
Public Class OrderedPerson
<RadSortOrder(3)>
Public Property LastName As String
<RadSortOrder(2)>
Public Property FirstName As String
<RadSortOrder(4)>
Public Property BirthDate As DateTime
<RadSortOrder(1)>
Public Property Id As Integer
<RadSortOrder(5)>
Public Property Address As String
Public Sub New(ByVal lastName As String, ByVal firstName As String, ByVal dateOfBirth As DateTime, ByVal id As Integer, ByVal address As String)
Me.LastName = lastName
Me.FirstName = firstName
Me.BirthDate = dateOfBirth
Me.Id = id
Me.Address = address
End Sub
End Class
2. Create a custom IComparer which will sort the properties considering the value of the RadSortOrderAttribute.
public class PropertyDescriptorComparer : System.Collections.IComparer
{
public int Compare(object x, object y)
{
if (x == y)
return 0;
if (x == null)
return 1;
if (y == null)
return -1;
PropertyDescriptor propertyDescriptorX = x as PropertyDescriptor;
PropertyDescriptor propertyDescriptorY = y as PropertyDescriptor;
RadSortOrderAttribute propertyOrderAttributeX =
propertyDescriptorX.Attributes[typeof(RadSortOrderAttribute)] as RadSortOrderAttribute;
RadSortOrderAttribute propertyOrderAttributeY =
propertyDescriptorY.Attributes[typeof(RadSortOrderAttribute)] as RadSortOrderAttribute;
if (Equals(propertyOrderAttributeX, propertyOrderAttributeY))
return 0;
if (propertyOrderAttributeX == null)
return 1;
if (propertyOrderAttributeY == null)
return -1;
return propertyOrderAttributeX.Value.CompareTo(propertyOrderAttributeY.Value);
}
}
Public Class PropertyDescriptorComparer
Implements System.Collections.IComparer
Public Function [Compare](x As Object, y As Object) As Integer Implements IComparer.[Compare]
If x.Equals(y) Then Return 0
If x Is Nothing Then Return 1
If y Is Nothing Then Return -1
Dim propertyDescriptorX As PropertyDescriptor = TryCast(x, PropertyDescriptor)
Dim propertyDescriptorY As PropertyDescriptor = TryCast(y, PropertyDescriptor)
Dim propertyOrderAttributeX As RadSortOrderAttribute = TryCast(propertyDescriptorX.Attributes(GetType(RadSortOrderAttribute)), RadSortOrderAttribute)
Dim propertyOrderAttributeY As RadSortOrderAttribute = TryCast(propertyDescriptorY.Attributes(GetType(RadSortOrderAttribute)), RadSortOrderAttribute)
If Equals(propertyOrderAttributeX, propertyOrderAttributeY) Then Return 0
If propertyOrderAttributeX Is Nothing Then Return 1
If propertyOrderAttributeY Is Nothing Then Return -1
Return propertyOrderAttributeX.Value.CompareTo(propertyOrderAttributeY.Value)
End Function
End Class
3. Last, but not least, create a derivative of BindingList<T> which implements the ITypedList interface. Thus, you can implement the GetItemProperties method which will make use of the newly created comparer to sort the properties and control their order. It is necessary to implement the GetListName method as well.
public class DataEntrySort<T> : BindingList<T>, ITypedList
{
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
PropertyDescriptorCollection typePropertiesCollection = TypeDescriptor.GetProperties(typeof(T));
return typePropertiesCollection.Sort(new PropertyDescriptorComparer());
}
public string GetListName(PropertyDescriptor[] listAccessors)
{
return string.Format("A list with Properties for {0}", typeof(T).Name);
}
}
Public Class DataEntrySort(Of T)
Inherits BindingList(Of T)
Implements ITypedList
Public Function GetItemProperties(listAccessors As PropertyDescriptor()) As PropertyDescriptorCollection Implements ITypedList.GetItemProperties
Dim typePropertiesCollection As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
Return typePropertiesCollection.Sort(New PropertyDescriptorComparer())
End Function
Public Function GetListName(listAccessors As PropertyDescriptor()) As String Implements ITypedList.GetListName
Return String.Format("A list with Properties for {0}", GetType(T).Name)
End Function
End Class
4. Now, you can use the new BindingList<T> you have just implemented:
this.radDataEntry1.DataSource = new DataEntrySort<OrderedPerson> { new OrderedPerson("Smith", "John", new DateTime(1980,1, 1), 12345, "452 Holly Lane Hopewell, VA 23860") };
Me.radDataEntry1.DataSource = New DataEntrySort(Of OrderedPerson) From {
New OrderedPerson("Smith", "John", New DateTime(1980, 1, 1), 12345, "452 Holly Lane Hopewell, VA 23860")
}
The properties are ordered according to the specified RadSortOrder attribute:
A complete solution providing a C# and VB.NET project is available here.