Welcome to WindowsClient.net | Sign in | Join

SilverLaw

Silverlight and WPF with VB.NET

Short And Simple: How To Sort An ObservableCollection(Of T) In Silverlight 3

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)

 

Comments

No Comments

Leave a Comment

(required) 

(required) 

(optional)

(required) 

Page view counter