Take a scoop of Silverlight Toolkit Pie Chart

Goldytech
Posted by in Silverlight category on for Beginner level | Views : 12601 red flag

A Complete walkthrough of creating Pie Chart with advanced features.
Introduction
Silverlight has come a long way from just being a media and graphics enhancements tool to full blown Line of Business Application platform.In this short post we will dive into the inner workings of Pie Chart that is available as a part of Silverlight Toolkit. Have a look at the image below which shows the output that we shall be working for.  PieChart
Control Templates and Styles
Silverlight is a great technology to work with. It gives so much leverage and freedom to developers that you can can completely override the default look of any control and give more sparkles to it by adding styles . In this post I shall be using the combination of both. Scott Guthrie has great post on his blog which discusses the control templates. I shall be targeting PieDataPoint, this class represents each slice in the pie chart. I shall be also using style palette which is part of System.Windows.Controls.DataVisualization.Toolkit assembly. In the style palette we will be setting the different backgrounds of each slice. Though this is completely optional if you don't specify the style palette , silverlight Charting engine takes the complete control and renders the colors of each slice automatically.Further using Styles and Control Templates I shall be changing the Legends that are getting displayed on the right side of the chart. I shall also be overriding the default tooltip text in the control template of PieDataPoint.
Getting Started
This post assumes that you have following software's installed on your computer. Create new project of SilverLight Application as displayed in the figure below Silverlight Application new project Add the references of following assemblies
  1. System.Windows.Controls.DataVisualization.Toolkit
  2. System.Windows.Controls.Toolkit

Any chart requires data for its display. Here in this example we will generate the random figures (between 1000 and 50000) of each month (Jan to Dec).I have created MonthlyCollection class for it , the Total property of this class will be binded to Chart ItemsSource. The complete code listing of this class is given below.

Public Class MonthlyCollection

Private _Month As String

Public Property Month() As String

Get

Return _Month

End Get

Set(ByVal value As String)

_Month = value

End Set

End Property

Private _Amount As Double

Public Property Amount() As Double

Get

Return _Amount

End Get

Set(ByVal value As Double)

_Amount = value

End Set

End Property

Public Shared ReadOnly Property Total() As List(Of MonthlyCollection)

Get Dim objMonthlyCollection As New List(Of MonthlyCollection)

Dim Rnd As New Random

With objMonthlyCollection

.Add(New MonthlyCollection With {.Month = "Jan", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Feb", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Mar", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Apr", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "May", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Jun", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Jul", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Aug", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Sep", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Oct", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Nov", .Amount = Rnd.Next(1000, 50000)})

.Add(New MonthlyCollection With {.Month = "Dec", .Amount = Rnd.Next(1000, 50000)})

End With

Return objMonthlyCollection

End Get

End Property

End Class

Now as the data is in place , let us now look at the control templates and styles code. As we will be using the animation for each slice in a simultaneous mode. Let us first look at the PieDataPoint control template.

<ControlTemplate x:Key="PieDataPoint" TargetType="Chart:PieDataPoint">
                <Path
                        Data="{TemplateBinding Geometry}"
                        Fill="{TemplateBinding Background}"
                        Stroke="{TemplateBinding BorderBrush}"
                        RenderTransformOrigin="0.5,0.5">
                    <Path.RenderTransform>
                        <ScaleTransform x:Name="Scale" ScaleX="0" ScaleY="0"/>
                    </Path.RenderTransform>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="RevealStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="0:0:0.5"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Shown">
                                <Storyboard>
                                    <DoubleAnimation
                                            Storyboard.TargetName="Scale"
                                            Storyboard.TargetProperty="ScaleX"
                                            To="1"
                                            Duration="0"/>
                                    <DoubleAnimation
                                            Storyboard.TargetName="Scale"
                                            Storyboard.TargetProperty="ScaleY"
                                            To="1"
                                            Duration="0"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Hidden">
                                <Storyboard>
                                    <DoubleAnimation
                                            Storyboard.TargetName="Scale"
                                            Storyboard.TargetProperty="ScaleX"
                                            To="0"
                                            Duration="0"/>
                                    <DoubleAnimation
                                            Storyboard.TargetName="Scale"
                                            Storyboard.TargetProperty="ScaleY"
                                            To="0"
                                            Duration="0"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ToolTipService.ToolTip>
                        <StackPanel Orientation="Horizontal" >
                            <ContentControl Content="Collection for " />
                            <ContentControl Content="{TemplateBinding IndependentValue}" />
                            <ContentControl Content=" is " />
                            <ContentControl DataContext="{TemplateBinding DependentValue}" Content="{Binding  Converter= {StaticResource DataFormatter},ConverterParameter=\{0:C\}}"  /> 
                          </StackPanel>
                    </ToolTipService.ToolTip>
                </Path>
            </ControlTemplate>

One thing in the above code that is worth observing is the ToolTip, using the powerful feature of control templates how am I transforming the mere tooltip text into useful information. Let us now look at how can I customize the Legends of the chart rather than just text.

<Style x:Key="LegendStyle" TargetType="Chart:LegendItem">

                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate  TargetType="Chart:LegendItem">
                            <Grid>
                                <Rectangle Fill="{Binding Background}" Stroke="{Binding BorderBrush}" StrokeThickness="1" Margin="1" />
                                <DataVisuals:Title Content="{TemplateBinding Content}" Margin="2" Foreground="White" />

                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

</Style>

In the above code I am using TemplateBinding to bind the content and showing each legend in rectangle with the appropriate background. Finally let us look into the StylePallete , as discussed above this is an optional step but would be good to have if you want more control on the output. Have a look at the code below.

<DataVisuals:StylePalette x:Key="PieDataPointPalette">
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FFF4F4F4"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FF5A88CE"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FFCE5A5A"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FFFFFF72"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="Blue"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="Red"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="Green"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="Pink"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="Cyan"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FF555555"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FF313861"/>
    </Style>
    <Style TargetType="Chart:PieDataPoint">
        <Setter Property="Template" Value="{StaticResource PieDataPoint}"/>
        <Setter Property="Background" Value="#FF000000"/>
    </Style>

</DataVisuals:StylePalette>

In this code I am targeting the style for the control template, PieDataPoint and setting its background property of various colors.One thing important to note here is that as my data represents of monthly collection which involves twelve months of the calendar. I need to specify twelve style attributes accordingly.The user can interact with the chart by clicking on the each slice of the pie chart. Once he click he gets corresponding info of the slice clicked on the labels on the right top.We can achieve this functionality by trapping the SelectionChanged event of Chart:PieSeries

Private Sub PieSeries_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
        If e.AddedItems.Count >= 1 Then
            Me.PnlInfo.DataContext = e.AddedItems(0)
        Else
            Me.PnlInfo.DataContext = Nothing
        End If
    End Sub

The above code assigns the first element of AddedItems Collection to the DataContext property of StackPanel.

Now let us look into the fetching of the new data, When user clicks on Refresh Data button the new data is binded to ItemsSource. Have a look at the code for the same.

Private Sub BtnRefresh_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

        Dim objPieSeries As DataVisualization.Charting.PieSeries
        objPieSeries = CType(Me.PieChart.Series(0), DataVisualization.Charting.PieSeries)
        objPieSeries.ItemsSource = MonthlyCollection.Total 
End Sub

Closure
There is a well known saying that picture is worth thousand words. You can bring your data to life by providing visuals animations to it. It can be great help to create digital dashboards. I hope you must have enjoyed reading the post. Download the sample code from here. Cheers and Happy Charting !
Page copy protected against web site content infringement by Copyscape

About the Author

Goldytech
Full Name: Muhammad Afzal Qureshi
Member Level: Bronze
Member Status: Member
Member Since: 8/4/2009 10:58:17 PM
Country: India

http://goldytech.wordpress.com
Hello Everyone Myself Muhammad Afzal , aka GoldyTech. Thats my pen name. I reside in India and work as a solution Architect on .NET platform. I hope you must have enjoyed reading my blog. Please leave your comments or suggestions good or bad and help me to improve

Login to vote for this post.

Comments or Responses

Posted by: Parasu on: 10/23/2009

Good examples, keep posting like this article.

-Paras


Login to post response

Comment using Facebook(Author doesn't get notification)