The ObservableCollection(Of T) doesn’t provide a simple sorting mechanism. One can use the OrderBy method but trying this I ended up in a mess of code. As I started I had a simple class for my Data objects called Debitor:
Imports System.ComponentModel
Public Class Debitor
#Region " Contructors "
Sub New()
' nix tun
End Sub
Public Sub New(ByVal name As String)
Me._name = name
End Sub
#End Region
#Region " Private Fields "
Private _name As String
#End Region
#Region " ReadOnly Properties "
Public ReadOnly Property Name() As String
Get
Return _name
End Get
End Property
#End Region
End Class
In MainPage I build an ObservableCollection(Of Debitor):
Private DebitorOC As ObservableCollection(Of Debitor)
Public Sub New()
InitializeComponent()
DebitorOC = New ObservableCollection(Of Debitor)
With DebitorOC
.Add(New Debitor("Zacharias"))
.Add(New Debitor("Adam"))
.Add(New Debitor("Junghans"))
End With
End Sub
My Debitor objects should be displayed as items in a Listbox, so I databound my ObservableCollection(Of Debitor) as ItemsSource to my Listbox:
<UserControl.Resources>
<local:Debitor x:Key="DebitorDataSource"
d:IsDataSource="True" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot"
Background="White"
DataContext="{Binding Source={StaticResource DebitorDataSource}}">
<ListBox x:Name="lbDebitors"
Margin="115,115,77,151"
IsSynchronizedWithCurrentItem="False"
ItemsSource="{Binding Name, Mode=OneWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
lbDebitors.ItemsSource = DebitorOC
End Sub
Everything was fine. But the problem was, that I wanted the Listbox to show the Items sorted. After trying different things I finally found a solution with five lines of code. Here it is:
Private Sub SortObservableCollection()
Dim ied As IEnumerable(Of Debitor) = _
From d In DebitorOC Order By (d.Name)
For Each i In ied
DebitorOC.Remove(i)
DebitorOC.Add(i)
Next
End Sub
And this is how it works:
I declare an IEnumerable(Of Debitor) to which I set the result of a LINQ query that is using the Order By clause:
Dim ied As IEnumerable(Of Debitor) = _
From d In DebitorOC Order By (d.Name)
The result is a sorted IEnumerable(Of Debitor). But to cast the IEnumerable(Of Debitor) to an ObservableCollection(Of Debitor) doesn’t work. I could set the IEnumerable(Of Debitor) ied as the ItemsSource of my Listbox to display sorted items but I didn’t want to touch my Data Binding. That’s where it getting tricky:
For Each i In ied
DebitorOC.Remove(i)
DebitorOC.Add(i)
Next
The above code is holding the working item in the variable i, round by round it removes the item out of the ObservableCollection(Of Debitor) and instantly adds it again at the end. The result is a sorted ObservableCollection(Of Debitor). That’s it.
Download SampleProject
Best regards,
M. (SilverLaw)