Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Styling the Chart Control in the Silverlight 4 Toolkit

0.00/5 (No votes)
22 Aug 2011 1  
Styling the chart control in the Silverlight Toolkit to create a new look and feel.

Introduction

I noticed that many people, including myself, have had some difficulties in styling the Chart control that comes with the Silverlight 4 Toolkit. It is relatively hard to go down the visual tree of the control in order to style the control in the Design view of Expression Blend so as to have a good look and feel. I searched the internet and I got little information on how to go about this process and I decided to work it through myself. I succeeded in restyling the chart control and the majority of the working is done in XAML. I think this article will ease the challenges of other developers/designers facing this same issue.

There are a series of Chart controls that come with the Silverlight 4 Toolkit, and some of these are listed below:

  • BarSeries
  • ColumnSeries
  • StackedColumnSeries
  • BubbleSeries
  • LineSeries
  • PieSeries
  • ScatterSeries

I will be discussing two of these series:

  • ColumnSeries
  • StackedColumnSeries

Note: You can follow the steps in this article both in Expression Blend 4 and Visual Studio 2010, but I will use Expression Blend 4 in this article. If you do not have the toolkit, it is available at Silverlight Toolkit - CodePlex.

ColumnSeries

With a new Silverlight Application created, I added a Chart control and edited the Template. In this article, I decided to delete the Legend and Chart Title from the Template as I will not need them. The Chart Title can still be of use so you can retain yours but the Legend is not useful as we will be using different colors for each column. The chart control now looks like this:

Chart1.png

Next, edit the XAML in order to bind the DependentValueBinding, IndependentValueBinding properties of the Chart control to a class which controls each column. The DataPointStyle property is also bound to a style created to control how the columns look. The XAML is:

<toolkit:Chart x:Name="GasChart" Style="{StaticResource GasChartStyle}" 
    BorderBrush="{x:Null}" Margin="4,141,0,60">
    <toolkit:ColumnSeries 
    DependentValueBinding="{Binding GasValue}" 
    IndependentValueBinding="{Binding GasName}" 
    DataPointStyle="{StaticResource ColorByGradeColumn}" 
    AnimationSequence="FirstToLast"/>
</toolkit:Chart>

The DataPointStyle is set to a StaticResource that sets the ControlTemplate for the ColumnDataPoint. At this point, we're changing how the columns will look. This look is a gloss-like column compared to the default ugly look. Paying close attention to the XAML code below, you will notice that the Background property of the Border in the ControlTemplate is bound to one of the properties (GasColor) of a class. This enables changing the column color dynamically:

<Style x:Key="ColorByGradeColumn" TargetType="toolkit:ColumnDataPoint">
    <Setter Property="Background" Value="DarkGray"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                <Border  Background="{Binding GasColor}" 
                         BorderBrush="{Binding GasColor}" 
                         BorderThickness="0.5">
                    <Grid Background="{x:Null}">
                        <ToolTipService.ToolTip>
                        <!--Provides the tooltip for each column -->
                            <StackPanel>
                                <ContentControl 
                                  Content ="{ TemplateBinding IndependentValue }"/>
                                <StackPanel Orientation="Horizontal">
                                      <ContentControl 
                                        Content ="{ TemplateBinding 
                                             FormattedDependentValue }"/>
                                    <ContentControl Content ="ppm"/>
                                </StackPanel>
                            </StackPanel>
                        </ToolTipService.ToolTip>
                        <Border BorderBrush="{x:Null}">
                            <Border.Background>
                                <!--This gradiesnt provides 
                                           the gloss-like feature for each-->
                                <LinearGradientBrush EndPoint="1.344,0.5" 
                                          StartPoint="-0.344,0.5">
                                    <GradientStop Color="White" Offset="0"/>
                                    <GradientStop Color="{Binding GasColor}" 
                                          Offset="0.5"/>
                                </LinearGradientBrush>
                            </Border.Background>
                        </Border>
                    </Grid>
                </Border>            
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Now, the class whose properties are bound to the Chart control is:

public class GasNameValue
{
    public double GasValue { get; set; }
    public string GasName { get; set; }
    public Brush GasColor { get; set; }
}

The method below creates new objects of the class above in a List where the values for each column are set. The number of objects created will determine the number of columns that your Chart will contain; most times your data comes from a database or cloud and this process will be dynamic rather than manual. The last line of code sets the ItemsSource of the Chart control to the List object.

private void SetData()
{
    List<GasNameValue> gasList = new List<GasNameValue>
    {
        new GasNameValue
        {
            GasName = "CO2",
            GasValue = 850.0,
            GasColor = new SolidColorBrush(Colors.Red)
        },
        new GasNameValue
        {
            GasName = "SO2",
            GasValue = 700.0,
            GasColor = new SolidColorBrush(Colors.Blue)
        },
        new GasNameValue
        {
            GasName = "CH4",
            GasValue = 820.0,
            GasColor = new SolidColorBrush(Colors.Green)
        },
        new GasNameValue
        {
            GasName = "NO2",
            GasValue = 600.0,
            GasColor = new SolidColorBrush(Colors.Yellow)
        },
        new GasName_Value
        {
            GasName = "F11",
            GasValue = 910.o,
            GasColor = new SolidColorBrush(Colors.Purple)
        },
        new GasNameValue
        {
            GasName = "F12",
            GasValue = 760.0,
            GasColor = new SolidColorBrush(Colors.Orange)
        },
    };
    ((ColumnSeries)GasChart.Series[0]).ItemsSource = gasList;
}

The final ColumnSeries looks like this:

Chart2.png

StackedColumnSeries

The default StackedColumnSeries looks like this (and it looks ugly to me):

Chart4.png

Now, when working with the StackedColumnSeries, after adding the Chart control and editing the Template as appropriate, you need to add the SeriesDefinition for each Stacked Column. The number of SeriesDefinitions that you add determines the number of partitions that you will end up having on each Stacked Column. The XAML below consists of six (6) partitions on each Stacked Column with properties bound to a class:

<toolkit:StackedColumnSeries>
    <toolkit:SeriesDefinition
        Title="CO2"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue1}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="SO2"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue2}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="NO2"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue3}" 
        IndependentValueBinding="{Binding Year}"/>
        <toolkit:SeriesDefinition
        Title="CH4"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue4}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="F11"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue5}" 
        IndependentValueBinding="{Binding Year}"/>
    <toolkit:SeriesDefinition
        Title="F12"
        ItemsSource="{Binding}"
        DependentValueBinding="{Binding GasValue6}" 
        IndependentValueBinding="{Binding Year}"/>
</toolkit:StackedColumnSeries>

This time around, in order to create a new color for each partition, a ResourceDictionaryCollection must be added to the chart palette; this ResourceDictionaryCollection contains six (6) Resource Dictionaries. Each ResourceDictionary provides the color for each partition on a stack. The XAML is like this:

<toolkit:Chart.Palette>
    <toolkit:ResourceDictionaryCollection>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="toolkit:ColumnDataPoint">
                <Setter Property="Background" Value="Red"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Red" BorderBrush="Red" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                 FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Red" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Blue"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Blue" 
                              BorderBrush="Blue" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                  FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Blue" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Green"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Green" 
                               BorderBrush="Green" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                   FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                        StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Green" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary><ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Yellow"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Yellow" 
                                BorderBrush="Yellow" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                  FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Yellow" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Purple"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Purple" 
                              BorderBrush="Purple" BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                              Content ="{ TemplateBinding 
                                                FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Purple" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
        <ResourceDictionary>
            <Style x:Key="DataPointStyle" TargetType="Control">
                <Setter Property="Background" Value="Orange"/>
                <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:ColumnDataPoint">
                        <Border Background="Orange" 
                                 BorderBrush="Orange" 
                                 BorderThickness="0.5">
                            <Grid Background="{x:Null}">
                                <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Horizontal">
                                              <ContentControl 
                                                Content ="{ TemplateBinding 
                                                   FormattedDependentValue }"/>
                                            <ContentControl Content =" ppm"/>
                                        </StackPanel>
                                </ToolTipService.ToolTip>
                                <Border BorderBrush="{x:Null}">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1.344,0.5" 
                                            StartPoint="-0.344,0.5">
                                            <GradientStop Color="White" Offset="0"/>
                                            <GradientStop Color="Orange" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            </Style>
        </ResourceDictionary>
    </toolkit:ResourceDictionaryCollection>
</toolkit:Chart.Palette>

Note that from the above code, the Chart is bound to a class but this time around, the colors are fixed, although it is still possible to dynamically change the colors by databinding the Background properties in the ControlTemplate.

The class to which the chart is bound is:

public class GasName_Value
{
    public string Year { get; set; }
    public double GasValue1 { get; set; }
    public double GasValue2 { get; set; }
    public double GasValue3 { get; set; }
    public double GasValue4 { get; set; }
    public double GasValue5 { get; set; }
    public double GasValue6 { get; set; }
}

The final StackedColumnSeries looks like this:

Chart3.png

These techniques can also be applied to other StackedColumn Series such as Stacked100ColumnSeries, StakedBarSeries, and Stacked100BarSeries, with very little manipulations. Happy Styling!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here