This post describes a method of using attached properties to bind a ViewModel which contains multiple data series to a Visiblox chart without any code-behind.
The Visiblox chart supports databinding in both WPF and Silverlight, where the X and Y values for each datapoint are bound to properties on an underlying model. However, there is no interface for binding a varying number of series (i.e a collection of collections). The solution provided here is similar to the one which Jeremiah Morrill published for binding multiple series to the Silverlight Toolkit charts, but with a few added extras, like series title binding and series type selection.
The solution is surprisingly simple, so I am going to dive straight into the code (note, I have collapsed the verbose attached property definitions so that just the interesting bits are shown below!)
The MultiSeries class defines a number of attached properties, Source is used to bind the collection of series, this property must be an IEnumerable, but if it also implements INotifyCollectionChanged, we handle the CollectionChanged events to update the chart (adding or removing series). The optional ItemsSourcePath is used to provide the path to the nested collection (more on this later) and the optional TitlePath binds the chart title. The XValuePath and YValuePath properties are used to bind the X & Y values of the chart. Finally, ChartTypeProvider is used to determine the series type (Line, Bar, Column ...) for each of the bound series. The provider must implement the following interface:
In most MVVM chart binding applications, you will probably want all the series to have the same type. To achieve this, we can create a simple implementation of this interface which always returns the same chart type:
In order to simplify the usage of this provider in XAML, we can provide a type converter which allows us to specify the required series type as a string, e.g. ChartTypeProvider="LineSeries", this makes use of the same framework mechanisms that allow you to specify a Fill as a string, e.g. Fill="Red", where the result will be to create the following, new SolidColorBrush() { Color = Colors.Red }, a suitable type converter is shown below:
A Simple Example
We'll start with a simple example, binding a collection of collections, in this case the harmonic vibrations of a string. The series are created as follows:
We can then use the attached properties defined above to bind this data to the chart. Note, because the bound data is a collection of collections (rather than a collection of items which expose the child collection via a property), the optional ItemsSourcePath is not required:
Whilst the MultiSeries class allows you to specify the chart type via ChartTypeProvider, it does not provide a mechanism for styling the various series which it produces based on the supplied Source. However, styling can be achieved using the chart's Palette, which is a collection of Style instances which are applied to the series in order.
The resulting chart is shown below:
A More Complex MVVM Example
In this example, rather than binding a collection of collections, the following model is bound:
CompanySalesViewModel has a collection of SalesTeamViewModel instances, each of these has a name, TeamName, and a collection of SalesInRegionViewModel instances. Note, SalesTeamViewModel also has a string indexer property which will be used to bind this model to a DataGrid.
A custom ChartTypeProvider is used so that we can select chart types based on the bound SalesTeamViewModel:
The view model is bound to a chart and is also bound to a DataGrid as follows. Note this time the ItemsSourcePath is used to bind the TeamSales property of each SalesTeamViewModel:
The result is show below, note that updating the data in the grid causes the chart to update accordingly:
I am CTO at Scott Logic and am a prolific technical author, blogger and speaker on a range of technologies.
My blog includes posts on a wide range of topics, including WebAssembly, HTML5 / JavaScript and data visualisation with D3 and d3fc. You'll also find a whole host of posts about previous technology interests including iOS, Swift, WPF and Silverlight.
I'm board member of FINOS, which is encouraging open source collaboration in the financial sector. I'm also very active on GitHub, contributing to a number of different projects.