Sorting in DataGrid with dynamic data

Oct 31, 2009 at 4:28 AM
Edited Oct 31, 2009 at 4:29 AM

I have a dynamic data source of the type List<Rate>. Rate is a type implementing the INotifyPropertyChanged interface. When any value updates the new data is immediately updated in the DataGrid, but it's not sorted with the new data.

Is there any workaround for this issue?

If you want to try it out, here's a shortened version of the code:

Window1.xaml

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:tk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
    Title="Window1" Height="300" Width="300" Name="Window1">
    <Grid>
        <tk:DataGrid Name="Rates" ItemsSource="{Binding}" AutoGenerateColumns="False">
            <tk:DataGrid.Columns>
                <tk:DataGridTextColumn Header="Symbol" Binding="{Binding Symbol}" IsReadOnly="True" />
                <tk:DataGridTextColumn Header="Ask" Binding="{Binding Ask, StringFormat=0.0000}" IsReadOnly="True" />
                <tk:DataGridTextColumn Header="Bid" Binding="{Binding Bid, StringFormat=0.0000}" IsReadOnly="True"/>
            </tk:DataGrid.Columns>
        </tk:DataGrid>
    </Grid>
</Window>

Window1.xaml.vb

Class Window1 

    Private _currentRates As List(Of Rate)

    Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded

        _currentRates = New List(Of Rate)
        _currentRates.Add(RandomRate("EUR/USD"))
        _currentRates.Add(RandomRate("GBP/JPY"))

        Rates.ItemsSource = _currentRates

        Dim timer As New Timers.Timer(1000)
        AddHandler timer.Elapsed, AddressOf Timer_Elapsed
        timer.Start()

    End Sub

    Private Shared rnd As New Random
    Private Shared ReadOnly Property RandomRate(ByVal symbol As String)
        Get
            Dim r = New Rate
            r.Symbol = symbol
            r.Ask = rnd.NextDouble() + 0.9
            r.Bid = rnd.NextDouble() + 0.9
            Return r
        End Get
    End Property

    Private Sub Timer_Elapsed(ByVal sender As Object, ByVal e As EventArgs)
        For Each r As Rate In _currentRates
            Dim newRate As Rate = RandomRate(r.Symbol)
            r.Ask = newRate.Ask
            r.Bid = newRate.Bid
        Next
    End Sub

End Class

Rate.vb

Imports System.ComponentModel

Public Class Rate
    Implements INotifyPropertyChanged

    Private _symbol As String
    Public Property Symbol() As String
        Get
            Return _symbol
        End Get
        Set(ByVal value As String)
            If _symbol <> value Then
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Symbol"))
                _symbol = value
            End If
        End Set
    End Property


    Private _ask As Double
    Public Property Ask() As Double
        Get
            Return _ask
        End Get
        Set(ByVal value As Double)
            If _ask <> value Then
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Ask"))
                _ask = value
            End If
        End Set
    End Property


    Private _bid As Double
    Public Property Bid() As Double
        Get
            Return _bid
        End Get
        Set(ByVal value As Double)
            If _bid <> value Then
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Bid"))
                _bid = value
            End If
        End Set
    End Property

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class

--

Regards,
Daniel