Click here to Skip to main content
15,885,435 members
Articles / Desktop Programming / WPF

How to create stock charts using the Silverlight Toolkit

Rate me:
Please Sign up or sign in to vote.
4.70/5 (15 votes)
16 Feb 2009CPOL2 min read 142K   2.7K   65  
An article on how to create a Candlestick stock chart using the Silverlight Toolkit.
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->

<UserControl x:Class="Microsoft.Windows.Controls.Samples.SeriesZoomSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:datavis="clr-namespace:Microsoft.Windows.Controls.DataVisualization;assembly=Microsoft.Windows.Controls.DataVisualization"             
    xmlns:charting="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;assembly=Microsoft.Windows.Controls.DataVisualization">

    <UserControl.Resources>
        <ControlTemplate TargetType="charting:Chart" x:Key="ZoomChartTemplate">
            <Border 
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="5">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                    <datavis:Title
                        Content="{TemplateBinding Title}"
                        Style="{TemplateBinding TitleStyle}"/>

                    <Grid Grid.Row="1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>

                        <datavis:Legend
                            x:Name="Legend"
                            Title="{TemplateBinding LegendTitle}"
                            Style="{TemplateBinding LegendStyle}"
                            Grid.Column="1"/>

                        <ScrollViewer 
                            x:Name="ScrollArea" BorderThickness="0" 
                            HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Hidden">
                            <Grid x:Name="ChartArea" Style="{TemplateBinding ChartAreaStyle}" Margin="0,10,0,20" >
                                <Grid x:Name="PlotArea" Style="{TemplateBinding PlotAreaStyle}">
                                    <Grid x:Name="GridLinesContainer" />
                                    <Grid x:Name="SeriesContainer" />
                                </Grid>
                            </Grid>
                        </ScrollViewer>
                    </Grid>
                </Grid>
            </Border>
        </ControlTemplate>

    </UserControl.Resources>

    <StackPanel Background="White">

        <ContentControl Content="Zooming a Series" Style="{StaticResource Header}"/>

        <charting:Chart HorizontalAlignment="Left" Width="450" Height="320" Template="{StaticResource ZoomChartTemplate}" x:Name="ZoomChart" Title="Zoomable">
            <charting:LineSeries
                Title="Widget Popularity"
                ItemsSource="{StaticResource WidgetPopularity}"
                IndependentValueBinding="{Binding Date}"
                DependentValueBinding="{Binding Percent}" />
            <charting:LineSeries
                Title="Gizmo Popularity"
                ItemsSource="{StaticResource GizmoPopularity}"
                IndependentValueBinding="{Binding Date}"
                DependentValueBinding="{Binding Percent}" />
        </charting:Chart>

        <StackPanel Margin="5,10,0,0" Orientation="Horizontal" >
            <TextBlock Text="Zoom:" />
            <Slider Margin="5,0,0,0" Width="250" Minimum="0" Maximum="500" ValueChanged="ZoomChanged" />
        </StackPanel>


        <src:SourceViewer xmlns:src="clr-namespace:Microsoft.Windows.Controls.Samples;assembly=Microsoft.Windows.Controls.Samples.Common" xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <src:SourceFile Path="SeriesZoomSample.xaml">
    <src:SourceFile.Source>
      <sys:String>&lt;!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
--&gt;

&lt;UserControl x:Class="Microsoft.Windows.Controls.Samples.SeriesZoomSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:datavis="clr-namespace:Microsoft.Windows.Controls.DataVisualization;assembly=Microsoft.Windows.Controls.DataVisualization"             
    xmlns:charting="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;assembly=Microsoft.Windows.Controls.DataVisualization"&gt;

    &lt;UserControl.Resources&gt;
        &lt;ControlTemplate TargetType="charting:Chart" x:Key="ZoomChartTemplate"&gt;
            &lt;Border 
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="5"&gt;
                &lt;Grid&gt;
                    &lt;Grid.RowDefinitions&gt;
                        &lt;RowDefinition Height="Auto"/&gt;
                        &lt;RowDefinition Height="*"/&gt;
                    &lt;/Grid.RowDefinitions&gt;

                    &lt;datavis:Title
                        Content="{TemplateBinding Title}"
                        Style="{TemplateBinding TitleStyle}"/&gt;

                    &lt;Grid Grid.Row="1"&gt;
                        &lt;Grid.ColumnDefinitions&gt;
                            &lt;ColumnDefinition Width="*"/&gt;
                            &lt;ColumnDefinition Width="Auto"/&gt;
                        &lt;/Grid.ColumnDefinitions&gt;

                        &lt;datavis:Legend
                            x:Name="Legend"
                            Title="{TemplateBinding LegendTitle}"
                            Style="{TemplateBinding LegendStyle}"
                            Grid.Column="1"/&gt;

                        &lt;ScrollViewer 
                            x:Name="ScrollArea" BorderThickness="0" 
                            HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Hidden"&gt;
                            &lt;Grid x:Name="ChartArea" Style="{TemplateBinding ChartAreaStyle}" Margin="0,10,0,20" &gt;
                                &lt;Grid x:Name="PlotArea" Style="{TemplateBinding PlotAreaStyle}"&gt;
                                    &lt;Grid x:Name="GridLinesContainer" /&gt;
                                    &lt;Grid x:Name="SeriesContainer" /&gt;
                                &lt;/Grid&gt;
                            &lt;/Grid&gt;
                        &lt;/ScrollViewer&gt;
                    &lt;/Grid&gt;
                &lt;/Grid&gt;
            &lt;/Border&gt;
        &lt;/ControlTemplate&gt;

    &lt;/UserControl.Resources&gt;

    &lt;StackPanel Background="White"&gt;

        &lt;ContentControl Content="Zooming a Series" Style="{StaticResource Header}"/&gt;

        &lt;charting:Chart HorizontalAlignment="Left" Width="450" Height="320" Template="{StaticResource ZoomChartTemplate}" x:Name="ZoomChart" Title="Zoomable"&gt;
            &lt;charting:LineSeries
                Title="Widget Popularity"
                ItemsSource="{StaticResource WidgetPopularity}"
                IndependentValueBinding="{Binding Date}"
                DependentValueBinding="{Binding Percent}" /&gt;
            &lt;charting:LineSeries
                Title="Gizmo Popularity"
                ItemsSource="{StaticResource GizmoPopularity}"
                IndependentValueBinding="{Binding Date}"
                DependentValueBinding="{Binding Percent}" /&gt;
        &lt;/charting:Chart&gt;

        &lt;StackPanel Margin="5,10,0,0" Orientation="Horizontal" &gt;
            &lt;TextBlock Text="Zoom:" /&gt;
            &lt;Slider Margin="5,0,0,0" Width="250" Minimum="0" Maximum="500" ValueChanged="ZoomChanged" /&gt;
        &lt;/StackPanel&gt;



    &lt;/StackPanel&gt;
&lt;/UserControl&gt;
</sys:String>
    </src:SourceFile.Source>
  </src:SourceFile>
  <src:SourceFile Path="SeriesZoomSample.xaml.cs">
    <src:SourceFile.Source>
      <sys:String>// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Linq;
using System.Diagnostics;
using System.Windows.Media;
using System.ComponentModel;

namespace Microsoft.Windows.Controls.Samples
{
    /// &lt;summary&gt;
    /// Charting sample that demonstrates zooming.
    /// &lt;/summary&gt;
    [Sample("Zoom", DifficultyLevel.Scenario)]
    [Category("DataVisualization")]
    public partial class SeriesZoomSample : UserControl
    {
        /// &lt;summary&gt;
        /// Caching of the ChartArea template part.
        /// &lt;/summary&gt;
        private Panel chartArea;

        /// &lt;summary&gt;
        /// Gets the ChartArea.
        /// &lt;/summary&gt;
        /// &lt;returns&gt;TemplatePart ChartArea&lt;/returns&gt;
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by ZoomChanged.")]
        private Panel ChartArea
        {
            get
            {
                if (chartArea == null)
                {
                    chartArea = GetLogicalChildrenBreadthFirst(ZoomChart).Where(element =&gt; element.Name.Equals("ChartArea")).FirstOrDefault() as Panel;
                }

                return chartArea;
            }
        }

        /// &lt;summary&gt;
        /// Caching of the ScrollArea template part.
        /// &lt;/summary&gt;
        private ScrollViewer scrollArea;

        /// &lt;summary&gt;
        /// Gets the ScrollArea.
        /// &lt;/summary&gt;
        /// &lt;returns&gt;TemplatePart ScrollArea&lt;/returns&gt;
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by an event handler in XAML.")]
        private ScrollViewer ScrollArea
        {
            get
            {
                if (scrollArea == null)
                {
                    scrollArea = GetLogicalChildrenBreadthFirst(ZoomChart).Where(element =&gt; element.Name.Equals("ScrollArea")).FirstOrDefault() as ScrollViewer;
                }
                return scrollArea;
            }
        } 

        /// &lt;summary&gt;
        /// Initializes a new instance of the ZoomIntoChartSample class.
        /// &lt;/summary&gt;
        public SeriesZoomSample()
        {
            InitializeComponent();

            this.Loaded += ZoomIntoChartSample_Loaded;
        }

        /// &lt;summary&gt;
        /// Force an update of the chart.
        /// &lt;/summary&gt;
        /// &lt;param name="sender"&gt;The ZoomIntoChartSample instance.&lt;/param&gt;
        /// &lt;param name="e"&gt;Event arguments.&lt;/param&gt;
        private void ZoomIntoChartSample_Loaded(object sender, RoutedEventArgs e)
        {
            // force synchronous layout pass
            ZoomChart.UpdateLayout();

            // and force initial zoom 
            UpdateChart(0);
        }
        
        /// &lt;summary&gt;
        /// Handles the changing of the zoomlevel.
        /// &lt;/summary&gt;
        /// &lt;param name="sender"&gt;The zoom slider.&lt;/param&gt;
        /// &lt;param name="e"&gt;Event arguments.&lt;/param&gt;
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by an event handler in XAML.")]
        private void ZoomChanged(object sender, RoutedPropertyChangedEventArgs&lt;double&gt; e)
        {
            Debug.Assert(ChartArea != null &amp;&amp; ScrollArea != null, "Zoom should not be called before layout has occurred");

            double zoom = e.NewValue;

            UpdateChart(zoom);
        }

        /// &lt;summary&gt;
        /// Updates the chart to zoom with the correct zoom factor.
        /// &lt;/summary&gt;
        /// &lt;param name="zoom"&gt;The percentage of zoom we wish to apply.&lt;/param&gt;
        private void UpdateChart(double zoom)
        {
            ChartArea.Width = ScrollArea.ViewportWidth + (ScrollArea.ViewportWidth * zoom / 100.0);
        }

        /// &lt;summary&gt;
        /// Helper function that returns a list of the visual children.
        /// &lt;/summary&gt;
        /// &lt;param name="parent"&gt;Element whose visual children will be returned.&lt;/param&gt;
        /// &lt;returns&gt;A collection of visualchildren.&lt;/returns&gt;
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by ChartArea and ScrollArea.")]
        private IEnumerable&lt;FrameworkElement&gt; GetLogicalChildrenBreadthFirst(FrameworkElement parent)
        {
            Debug.Assert(parent != null, "The parent cannot be null.");

            Queue&lt;FrameworkElement&gt; queue =
                new Queue&lt;FrameworkElement&gt;(GetVisualChildren(parent).OfType&lt;FrameworkElement&gt;());

            while (queue.Count &gt; 0)
            {
                FrameworkElement element = queue.Dequeue();
                yield return element;

                foreach (FrameworkElement visualChild in GetVisualChildren(element).OfType&lt;FrameworkElement&gt;())
                {
                    queue.Enqueue(visualChild);
                }
            }
        }

        /// &lt;summary&gt;
        /// Helper function that returns the direct visual children of an element.
        /// &lt;/summary&gt;
        /// &lt;param name="parent"&gt;The element whose visual children will be returned.&lt;/param&gt;
        /// &lt;returns&gt;A collection of visualchildren.&lt;/returns&gt;
        private IEnumerable&lt;DependencyObject&gt; GetVisualChildren(DependencyObject parent)
        {
            Debug.Assert(parent != null, "The parent cannot be null.");

            int childCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int counter = 0; counter &lt; childCount; counter++)
            {
                yield return VisualTreeHelper.GetChild(parent, counter);
            }
        }
    }
}</sys:String>
    </src:SourceFile.Source>
  </src:SourceFile>
</src:SourceViewer>



    </StackPanel>
</UserControl>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
South Africa South Africa
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions