Introduction
Keeping up with new tooling, technologies, and techniques is a challenge for software developers that requires some dedicated effort. This article demonstrates building a web based interactive chart, and is my attempt to assimilate some of the recent updates and best practices that have emerged with Visual Studio 2010 and .NET Framework 4 into my software lexicon.
Requirements
The chart for this article is a visualisation of the Coppock Indicator for the ASX (Australian Stock Exchange). The Coppock Indicator provides a signal for investors that a bear market has ended and it is time to begin building long term positions in strong companies. The chart will be integrated into a web page that discusses the management of risk when investing in shares. There is over 100 years of data available for the Coppock Indicator, so the interactivity for this chart will be an ability to filter the range.
Chart Basics
Charts are one of the fun parts of math. They show how variables relate in a visual way that conveys meaning at a glance. The variables for the Coppock Indicator are dates and a corresponding value. The date is identifiable as an independent variable (its value is not influenced by other factors), and the value is identifiable as a dependent variable (it's affected by the average price of stocks over time). It is typical to display the independent variable as the horizontal (X) axis and the dependent variable as the vertical (Y) axis. The chart most suitable for the Coppock Indicator is a Point-to-Point graph because the Coppock Indicator is calculated on the last day of each month.
Choosing the Technologies
My background is in enterprise development using C# and the .NET Framework, and I wanted to try out the latest Visual Studio 2010. The choice of technology then starts with which platform to target (web, desktop, or mobile) to reach my intended user. My initial research started with Silverlight because of its ability to target all of the platforms (including Mobile with Windows Phone 7) with an extensive set of components in the Silverlight Toolkit. Another option considered was the web standards platform of HTML and JavaScript (JQuery has charting components). The web standards platform tools are light-weight and, when targeting online users, are likely an ideal choice. As an enterprise developer, I want to focus my learning on targeting a broad audience (customers, external business partners, and users within the business). My choice for building the Coppock Indicator Chart is Silverlight 4 with ASP.NET, and will demonstrate Silverlight's ability to encapsulate rich user experiences into a component that can be integrated with web pages. You can download the tools required for compiling and running the Coppock Charting application from the Silverlight website.
Charting Component for Silverlight
The Silverlight Toolkit contains charting components that provide design time support and also dynamic update at runtime when the underlying data source changes. These chart controls behave consistently with the standard Silverlight controls, e.g., are defined declaratively in XAML and can be styled or completely re-templated if required to achieve a desired layout. The chart components also provide extensibility points; e.g., individual parts of the chart can be replaced with custom built components if the existing functionality doesn’t meet requirements. Note: The charting components in the Silverlight Toolkit are still in the ‘Preview Band’, and could change before being added to the Silverlight SDK.
Declarative User Interface
XAML is a fundamental part of Silverlight. It ensures a separation of concern between user interface layout and application logic because in XAML, it's only possible to declare interface components and their interaction (via triggers). Business logic must be specified in code, and is wired up to elements in the XAML through databinding to properties, events, and commands. XAML can be thought of as declarative programming because every element corresponds to either a class in the .NET Framework or a class in your application.
<chartingToolkit:Chart x:Name="coppockChart"
Title="{Binding ChartTitle}"
Margin="10,5,15,5"
Style="{StaticResource chartStyle}">
<chartingToolkit:LineSeries Title="Coppock Indicator"
DependentValuePath="Value"
IndependentValuePath="Date"
ItemsSource="{Binding Source={StaticResource coppockDataView}}"
DataPointStyle="{StaticResource simpleLineDataPointStyle}"
LegendItemStyle="{StaticResource legendItemStyle}"
Loaded="LineSeries_Loaded">
</chartingToolkit:LineSeries>
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="Y"
Minimum="{Binding AxisYMinimum}"
Maximum="{Binding AxisYMaximum}"
Interval="{Binding AxisYInterval}"
ShowGridLines="True"
Location="Right" />
<chartingExtensions:EndOfMonthAxis Orientation="X"
Title=""
ShowGridLines="False"
Maximum="{Binding AxisXMaximum}"
Interval="{Binding AxisXInterval}"
IntervalType="{Binding AxisXIntervalType}"
AxisLabelStyle="{StaticResource axisLabelStyle}">
</chartingExtensions:EndOfMonthAxis>
</chartingToolkit:Chart.Axes>
</chartingToolkit:Chart>
Databinding and MVVM
The databinding mechanism in Silverlight ensures that modified values are synchronised between the user interface and the underlying code; e.g., when the date range for the Coppock Indicator chart is changed, the chart title is updated to show the new date values. Code classes implementing the INotifyPropertyChanged
Interface can participate in this databinding mechanism.
Title="{Binding ChartTitle}"
Code:
public string ChartTitle
{
get
{
return this.chartTitle;
}
private set
{
this.chartTitle = value;
this.NotifyPropertyChanged("ChartTitle");
}
}
An important best practice to emerge in programming for Silverlight is the MVVM (Model-View-ViewModel) design pattern. This pattern encourages separation of business logic code from code that manipulates the view directly. ViewModel classes can be statically initialised in XAML.
<UserControl.Resources>
<viewModels:CoppockViewModel x:Key="coppockViewModel"
SeriesChanged="ViewModel_SeriesStartChanged" />
</UserControl.Resources>
The ViewModel is then made available to all elements in XAML through the DataContext
property.
DataContext="{Binding Source={StaticResource coppockViewModel}}"
Making the Chart Interactive
Clicking the Coppock Charts date range HyperlinkButton
s will execute a command that causes the chart's datasource to be filtered to reflect the chosen date range. A binding applied to the HyperlinkButton
's Command
property connects it to the ChangeSeriesStart
DelegateCommand which is located in the ViewModel class.
<HyperlinkButton x:Name="TenYearSeriesButton"
Content="10yr"
HorizontalContentAlignment="Center"
Command="{Binding ChangeSeriesCommand}"
CommandParameter="{Binding TenYearSeriesCommandParameter}"
Width="30" />
When the ChangeSeriesStart
DelegateCommand is initialised, an event handler is assigned to its Action
property, which executes when the HyperlinkButton
is clicked.
this.ChangeSeriesCommand = new DelegateCommand(this.ChangeSeriesStart,
this.CanChangeSeriesStart);
The ability to filter the chart by date range is enabled by the CollectionViewSource
type. CollectionViewSource
wraps the actual DataSource of the CoppockChart and exposes a View property that is implicitly used when DataBinding occurs. When CollectionViewSource
is refreshed, it executes the Filter
event which allows each item in the DataSource to be examined to determine if it should be included in the View. DataBinding ensures that this change to the CollectionViewSource
View is reflected in the chart.
<Grid.Resources>
<CollectionViewSource x:Key="coppockDataView"
Source="{Binding CoppockData.SeriesData}"
Filter="SeriesData_Filter"/>
</Grid.Resources>
Code:
private void SeriesData_Filter(object sender, FilterEventArgs e)
{
if (e.Item != null)
{
e.Accepted = this.ViewModel.IncludeInSeries(((DataItem)e.Item).Date);
}
}
Locating the Signal Markers
The purpose of the Coppock Indicator is to provide a signal that indicates when the bear market has ended. The algorithm to determine this signal looks for DataItem
s where the value is less than zero but greater than the previous month's value. A LinkedList
is used as the underlying datasource because of this need to inspect the previous item. When a DataItem
is found that represents the Coppock Indicator signal, a line and an ellipse with a ToolTip
is drawn onto a Canvas
that overlays the chart (this technique is described in another article).
private void ViewModel_SeriesStartChanged(object sender, SeriesStartChangedEventArgs e)
{
this.DataView.View.Refresh();
this.ChartAreaCanvas.Children.Clear();
this.DrawSignalMarkers();
}
Chart Extensibility
Each component that makes up the chart (Series
and Axis
) is a control. This means that styles can be applied, templates can be modified, or the control can be derived from or even totally replaced with a custom component. To properly display the Coppock Indicator data, end of month values were required for the horizontal X axis. The DateTimeAxis
available with the Silverlight Toolkit didn't support this scenario, but by creating a class derived from the standard DateTimeAxis
, it was possible to override the GetMajorAxisValues
method and modify the DateTime
value to display.
public class EndOfMonthAxis : DateTimeAxis
{
protected override IEnumerable<DateTime> GetMajorAxisValues(Size availableSize)
{
return base.GetMajorAxisValues(availableSize).
Select(date => date.AddDays(-1));
}
}
Then a style is applied to the StringFormat
property of the AxisLabel
to format the date.
<Style x:Key="axisLabelStyle" TargetType="chartingToolkit:AxisLabel">
<Setter Property="StringFormat" Value="{}{0:MMM yy}" />
</Style>
Integration with the HTML page
This Coppock Indicator chart emphasises Silverlight as a component part of a web page. This, I think, requires the Silverlight application to be configurable by its hosting page; i.e., as the web page renders in the browser, I would like to perform custom initialisation on the Silverlight component. Initialisation parameters are specified as name value pairs in the initParams
member of the object
tag hosting the Silverlight application. Any number of name value pairs can be specified in the initParams
value (comma separated). The Silverlight Plug-in Object Reference provides a complete reference for integration with the HTML page.
<name="initParams" value="Chart=Coppock" />
These parameters can then be extracted from StartupEventArgs
in the Application_Startup
event.
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainView(e.InitParams);
}
Parameters are iterated over using the Keys
property.
foreach (var key in this.InitParams.Keys)
{
var param = this.InitParams[key];
...
}
Making the Business Case for Silverlight
Silverlight is a rich client technology built on the .NET Framework that can target web, desktop, and mobile platforms using the rich debugging environment provided by Visual Studio. Silverlight brings us closer to the concept of a single code base targeting multiple platforms. This article has discussed Silverlight's abilities as a component in a web page with HTML and JavaScript integration. This approach to using Silverlight opens the door to SAAS (Software as a Service), where Silverlight applications can be independently hosted, e.g., using the Windows Azure Platform and integrated into a website by specifying the web address. This enables scenarios where an enterprise may want to expose application functionality to business partners or may want to consume components built externally and integrate them into web based applications.
References
History
- 29 May, 2010: Version 1.0 (Initial version).