Monday, December 29, 2008

Discovering RelativeSource.PreviousData

When working with Data Binding in WPF, I have found the RelativeSource class very useful. This class is useful when you want to bind to a source relative to the binding target. For example you may want to bind the Width of a control to its Height. In this case RelativeSource.Self can be used. Or you may want to bind to an element that is an ancestor of the binding target. Here you would use RelativeSource.FindAncestor.

But there was another use of RelativeSource that I was not aware of until recently - RelativeSource.PreviousData. Let me explain where this might be useful. Say you have data bound an ItemsControl like a ListBox to a collection of data items. You have written a DataTemplate to define how each item must be displayed within the ItemsControl. Within the DataTemplate you have access to the current data item. But what if you also want access to the previous data item?



For example, you may be displaying the stock values for a company as a chart as shown below.



Each bar in the chart represents one data item within the ItemsControl. But within each item(above the bar), you also want to show the increase/decrease of the stock value when compared to the previous stock value. This is where RelativeSource.PreviousData is useful as shown below.


<DataTemplate x:Key="RecordTemplate">


...........


...........


<TextBlock Margin="3,0,0,3">


<TextBlock.Text>


<MultiBinding Converter="{StaticResource RecordsDifferenceConverter}">


<Binding/>


<Binding RelativeSource="{RelativeSource PreviousData}"/>


MultiBinding>


TextBlock.Text>


TextBlock>


...........


...........


</ DataTemplate


In the above XAML snippet, the MultiValueConverter accepts the value of the current item and the value of the previous item, and returns the difference between the two. This is displayed above each bar in the chart.



The source code for this sample may be found here. Keep in mind that this is not a fully implemented chart – there are so many things missing. I just wanted to illustrate where RelativeSource.PreviousData may be useful.