Every now and again I revisit my obsession with data-binding to XML data and Silverlight and this is one of those posts.
Now, to be fair, this was prompted by chatting to Rich who pointed me at one of my old blog posts about binding to XML data;
which I fully accept has a bunch of limitations but does (via a hacky use of being able to bind to string indexers) get you some way towards binding to XML.
In that blog post, I wrote two classes – BindableXNode and XmlDataSource and I’ll repeat neither of them here.
Our chat was about binding from XML data onto a Silverlight Toolkit charting control and, specifically, binding multiple datasets onto a single chart from that XML.
Now, I don’t think that a Silverlight Toolkit chart control has a facility to bind to multiple sources of chart data at a time and so I borrowed a simplified version of a MultiChart control from this excellent blog post by Beat which adds a SeriesSource property to the ChartControl ( it also does a little more that I didn’t need so I removed those bits for simplicity ).
Then I wrote a little XML file of test data;
<?xml version="1.0" encoding="utf-8" ?> <dataSets> <dataSet title="Two Times Table"> <data x="1" y="2"/> <data x="2" y="4"/> <data x="3" y="6"/> <data x="4" y="8"/> <data x="5" y="10"/> </dataSet> <dataSet title="Three Times Table"> <data x="1" y="3"/> <data x="2" y="6"/> <!-- you get the idea, it goes up to 5 times table --> </dataSets>
and I dropped this into my ClientBin folder on my web site within a new Silverlight project;
Now, time to read it and bind it onto the screen. Here’s the simple UI I ended up with;
In the left hand column is a ListBox which is displaying the 5 charts separately whilst in the right hand column is a MultiChart displaying all the lines on a single chart.
Here’s the XAML I ended up with (there’s no code in this blog post, it’s a XAML-only zone );
<UserControl x:Class="XmlTestApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:XmlTestApp" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"> <!-- My kingdom for a markup extension 🙂 --> <UserControl.Resources> <local:XmlDataSource x:Key="dataSource" DownloadUri="data.xml" /> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <ListBox DataContext="{StaticResource dataSource}" ItemsSource="{Binding Path=Xml.[descendant-or-self::dataSet]}"> <ListBox.ItemTemplate> <DataTemplate> <Border BorderBrush="Black" CornerRadius="2" Margin="3" Padding="3"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition MaxHeight="144" /> </Grid.RowDefinitions> <TextBlock Margin="3" HorizontalAlignment="Center" Text="{Binding Path=[string(attribute::title)]}" /> <toolkit:Chart Grid.Row="1" Margin="3" HorizontalAlignment="Center" Title="{Binding Path=[string(attribute::title)]}"> <toolkit:Chart.Series> <toolkit:LineSeries Title="{Binding Path=[string(attribute::title)]}" ItemsSource="{Binding Path=[child::data]}" DependentValueBinding="{Binding Path=[number(attribute::y)]}" IndependentValueBinding="{Binding Path=[number(attribute::x)]}" /> </toolkit:Chart.Series> </toolkit:Chart> </Grid> </Border> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <local:MultiChart Grid.Column="1" DataContext="{StaticResource dataSource}" SeriesSource="{Binding Path=Xml.[descendant-or-self::dataSet]}"> <local:MultiChart.SeriesTemplate> <DataTemplate> <toolkit:LineSeries Title="{Binding Path=[string(attribute::title)]}" ItemsSource="{Binding Path=[child::data]}" DependentValueBinding="{Binding Path=[number(attribute::y)]}" IndependentValueBinding="{Binding Path=[number(attribute::x)]}" /> </DataTemplate> </local:MultiChart.SeriesTemplate> </local:MultiChart> </Grid> </UserControl>
and so this is using my XmlDataSource class to asynchronously download data.xml. It then sets up a bunch of bindings;
- ListBox – ItemsSource = dataSet elements
- TextBlock – Text = title attribute
- Chart
- LineSeries
- Title = title attribute
- ItemsSource = data child elements
- DependentValueBinding = y attribute
- IndependentValueBinding = x attribute
- MultiChart – SeriesSource = dataSet elements
- SeriesTemplate
- LineSeries (bound up as before & duplicated here)
and that’s pretty much it. Async download of XML and charts onto the screen with no “code” to write but a lot of XAML to play around with.
Here’s the project for download.
Please note this includes a source file that is not mine (MultiChart.cs) and I’ve clearly marked it that way. You should contact the original author around use of his work.