Introduction
In the first part, I outlined the sample application and said that it:
- will create a collection of Person objects and databind them to a ListBox.
- will use very simple DataTemplates to format two properties of the Person class - FullName and Status.
- will use a GroupStyle HeaderTemplate to display a third property of the Person class - Category.
- groups the Person objects by their Category property.
- sorts the Categories and displays them in alphabetical order.
- sorts the Persons by name inside the Category groups and displays them in alphabetical order.
The first five tasks are all covered in that previous part. You can download the project up to this point from here.
Sorting the Categories
In the same way that I used a Group Description to group items together, WPF offers the SortDescription to allow data inside the CollectionView to be sorted. The following code in the Window Loaded event is all that's needed:
currentView.SortDescriptions.Add(New SortDescription("Category", ListSortDirection.Ascending))
The SortDescription takes two parameters. The first is the name of the property that you want to sort on. The second is one of two choices for the sort direction.
For completeness, this is the full code so far in the Window Loaded event (which creates the DataContext, the View, the GroupDescription and the SortDescription):
Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Contacts = Person.GetPersons
Me.DataContext = Contacts
Dim currentView As ICollectionView
currentView = CollectionViewSource.GetDefaultView(Contacts)
' Group
currentView.GroupDescriptions.Add(New PropertyGroupDescription("Category"))
' Sort Categories
currentView.SortDescriptions.Add(New SortDescription("Category", ListSortDirection.Ascending))
End Sub
The sorted Categories will look like this:

Sorting the ListItems
As you can see, the Categories are now in alphabetical order. The names of the Person objects however are still shown in the relative order in which they were created. To create this secondary sort, the same kind of code is used:
currentView.SortDescriptions.Add(New SortDescription("FullName", ListSortDirection.Ascending))
The resulting display is:

The clearest example is where you can see the three items in the 'Work Colleagues' Category. They are now sorted alphabetically.
Note that the order that you list the sorting tasks is important. If you were to reverse the order:
' Sort individual names
currentView.SortDescriptions.Add(New SortDescription("FullName", ListSortDirection.Ascending))
' Sort Categories
currentView.SortDescriptions.Add(New SortDescription("Category", ListSortDirection.Ascending))
You would effectively lose the Category sort.

It is possible to create and apply the grouping and sorting in XAML, but I always try as far as possible to handle these kind of tasks in code-behind. Equally, I try and use XAML for the actual graphical display. There isn't a clear line between the two sometimes, of course, and you have to allow for individual preferences, but I try and keep to this approach as a general rule.