Display Live Data In Silverlight Using ObservableCollection and INotifyPropertyChanged

Download Source Code | Run Sample

Articles shows how to use ObservableCollection in combination with an object implementing INotifyPropertyChanged interface to display live data in Silverlight Application.

ObservableCollection is a generic dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed and INotifyPropertyChanged provides PropertyChanged notification to clients when any property value gets changed.

Sample Application in Nutshell

We are going to create a simple Silverlight Application which show DataGrid with user names and their respective scores, we will also create a simple Column Chart to display same user data. We will set ItemSource of both control to the same instance of ObservableCollection and finally we will create timer which will randomly update ObservableCollection by adding new row or updating score for random users.

User Class.

As you can see User Class implements INotifyPropertyChange interface, INotifyPropertyChange defines PropertyChanged Event which notifies subscriber on any change in properties, This is very important if you do not implement INotifyPropertyChange interface then any change in your property will not trigger updates in either datagrid and chart.

public class  User : INotifyPropertyChanged{
    
private string  name ;

    public string 
Name{
        
get  return  name }
        
set  {
            
if  ( value  ! name){
                name 
= value;
                
onPropertyChanged( this "Name" ) ;
            
}
        }
    }

    
private long  score ;

    public long 
Score{
        
get  return  score }
        
set  {
            
if  (score ! = value ) {
                score 
= value;
                
onPropertyChanged( this "Score" ) ;
            
}
        }
    }

    
#region  INotifyPropertyChanged Members

    
public event  PropertyChangedEventHandler PropertyChanged ;

    private void 
onPropertyChanged( object  sender
        , 
string  propertyName){

        
if  ( this .PropertyChanged ! = null ){
            PropertyChanged(sender, 
                
new  PropertyChangedEventArgs(propertyName)) ;
        
}
    }

    
#endregion
}

Observable Collection of User

As I mentioned earlier ObservableCollection implements INotifyCollectionChanged interface which defines CollectionChanged event which notifies subscribers on any change in collection, Unless you use ObservableCollection or custom class which implements INotifyCollectionChanged, updates that you make in collection will not trigger update in either datagrid or chart.

ObservableCollection<User> getUserCollection()
{
    ObservableCollection<User> rVal 
= new  ObservableCollection<User>() ;

    
rVal.Add( new  User { Name  "Tom" , Score  }) ;
    
rVal.Add( new  User { Name  "Sam" , Score  }) ;
    
rVal.Add( new  User { Name  "John" , Score  }) ;
    
rVal.Add( new  User { Name  "Dave" , Score  }) ;
    
rVal.Add( new  User { Name  "Sue" , Score  }) ;

    return 
rVal ;
}


XAML Layout and Databinding.

We have a very simple XAML layout which includes DataGrid in top and Charting Control in bottom, Charting control has one ColumnSeries without any data.

< Grid  x:Name ="LayoutRoot"  Background ="White">
        
< Grid.RowDefinitions >
            
< RowDefinition  Height ="*"   />
            <
RowDefinition  Height ="300"   />
        </
Grid.RowDefinitions >
        
< data:DataGrid  x:Name ="dataGrid"  Grid.Row ="0"   >      
        
</ data:DataGrid >

        
< charting:Chart  x:Name ="chartControl"  Grid.Row ="1"  Title ="Live Chart">
            
< charting:Chart.Series >
                
< charting:ColumnSeries  DependentValueBinding ="{Binding Score}"
                                    IndependentValueBinding
="{Binding Name}"   />
            </
charting:Chart.Series >
        
</ charting:Chart >
 
</ Grid >

We will use constructor to bind our data to datagrid and chart, we are also creating a timer which starts after 10 seconds and ticks every 2 second, we are going to randomly change data and add or remove row in collection whenever timer event fires.

ObservableCollection<User> users ;
 
Timer timer ;
        
 public 
Page()  {
            InitializeComponent()
;

            
users  getUserCollection() ;

            this
.dataGrid.ItemsSource  users ;

            
((DynamicSingleSeriesWithAxes) this .chartControl.Series[ 0 ]).ItemsSource  users ;

            
timer  = new  Timer(timerFired, null , 10000 , 5000 ) ;           
 
}


Updating Data

Very important thing to note here is the way in which we have to make updates to our datasource when we are not in UI thread, if you are familiar with Winforms development then you should be familiar with cross-thread access exception when you try to update UI element from another thread. Similar to windows development you will have to use BeginInvoke to make any updates to UI Element or In our case object which can trigger change in UI Element.

void  timerFired( object  state){
    
this .Dispatcher.BeginInvoke( delegate (){
        Random rnd 
= new  Random() ;
        
users[rnd.Next( 0 ,users.Count)].Score  rnd.Next( 1 5 ) ;

        if 
(rnd.Next( 1 5 ) >  3 ) {
            
if  (users.Count >  4 ){
                users.RemoveAt(
4 ) ;
            
else  {
                users.Add(
new  User { Name  "Sue" , Score  }) ;
            
}
        }
    })
;
 
}

We are randomly selecting a row in collection and updating its score, along with that we are also randomly adding or removing row from the collection. Although we are not rebinding our data with DataGrid or Chart they both with immediately get updated whenever source changes.


Closing Notes

You also get two way binding with INotifyPropertyChanged and DataGrid without adding single line of additional code, if you update Score or Name in DataGrid change will immediately trigger in change Chart Control.

7 Comments

Comments have been disabled for this content.