Columns of a different color [Customizing the appearance of Silverlight charts with re-templating and MVVM]


This blog has moved to a new location and comments have been disabled.

All old posts, new posts, and comments can be found on The blog of dlaa.me.

See you there!

Comments (19)
  1. In this issue: Corey Schuman, Alex Golesh, Jordan Knight, Jesse Liberty, and David Anson. From SilverlightCream

  2. It’s been a couple of months since I shared my semi-comprehensive page of Charting resources on the web

  3. ovidiutudorache says:

    If I use the following code in your Border, I should see the column being split in two: red and yellow. But that doesn’t happen. Why?

    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" >

    <Grid>

    <Grid.RowDefinitions>

    <RowDefinition />

    <RowDefinition />

    </Grid.RowDefinitions>

    <Border Background="Red" />

    <Border Grid.Row="1" Background="Yellow" />

    </Grid>

    </Border>

  4. Delay says:

    ovidiutudorache,

    I’m not sure what the problem you’re seeing is – when I try the same thing you’re doing, it works fine for me. Maybe you could compare what you’ve got with the working example below to see what might be different enough to be causing a problem?

    Hope this helps!

    <charting:Chart>

       <charting:Chart.Series>

           <charting:ColumnSeries

               DependentValuePath="Y">

               <charting:ColumnSeries.ItemsSource>

                   <PointCollection>

                       <Point Y="0"/>

                       <Point Y="1"/>

                       <Point Y="2"/>

                   </PointCollection>

               </charting:ColumnSeries.ItemsSource>

               <charting:ColumnSeries.DataPointStyle>

                   <Style TargetType="charting:ColumnDataPoint">

                       <Setter Property="Template">

                           <Setter.Value>

                               <ControlTemplate TargetType="charting:ColumnDataPoint">

                                   <Grid>

                                       <Grid.RowDefinitions>

                                           <RowDefinition/>

                                           <RowDefinition/>

                                       </Grid.RowDefinitions>

                                       <Border Grid.Row="0" Background="Red"/>

                                       <Border Grid.Row="1" Background="Yellow"/>

                                   </Grid>

                               </ControlTemplate>

                           </Setter.Value>

                       </Setter>

                   </Style>

               </charting:ColumnSeries.DataPointStyle>

           </charting:ColumnSeries>

       </charting:Chart.Series>

    </charting:Chart>

  5. TreeUK says:

    Your more recent post on SetterValueBindingHelper did an awesome job of making what you’re doing in this post much easier.

    Awesome work!

  6. Crystal.ice says:

    1. The ControlTemplate already change to

    <Grid Background=

    "{Binding brush4VolumDataPointsColor}"

    >

    and

    <Rectangle>

    <Rectangle.Fill>

    <LinearGradientBrush>

    <GradientStop

    Color="#ff80ffff"

    Offset="0"/>

    <GradientStop

    Color="#ff0000ff"

    Offset="1"/>

    </LinearGradientBrush>

    </Rectangle.Fill>

    are work well.

    and

    The test statement

    oStockDataPoint.dVolum = oStockDataPoint.dVolum * -1;

    are work well!

    but

    brush4VolumDataPointsColor = new SolidColorBrush { Color = Colors.Red };

    no effect! color value are zero (perhaps) (no color).

    why?

    Thank you very much!

    ///////////////////////////////////////////

    using System.ComponentModel;

    using System.Windows.Media;

    namespace INotifyPropertyChanged1

    {

    public class StockDataPointViewModel

    : INotifyPropertyChanged

    {

    public event PropertyChangedEventHandler PropertyChanged;

    public cStockDataPoint oStockDataPoint{ get; private set; }

    public Brush brush4VolumDataPointsColor{ get; private set; }

    public StockDataPointViewModel(cStockDataPoint StockDataPoint)

    {

    oStockDataPoint = StockDataPoint;

    oStockDataPoint.PropertyChanged += new PropertyChangedEventHandler(HandleStockDataPointPropertyChanged);

    }

    void HandleStockDataPointPropertyChanged(object sender, PropertyChangedEventArgs e)

    {

    if(e.PropertyName == "dVolum")

    {

    if(oStockDataPoint.dVolum < 0)

    {

    brush4VolumDataPointsColor = new SolidColorBrush { Color = Colors.Red };

    oStockDataPoint.dVolum = oStockDataPoint.dVolum * -1;

    }

    else

    {

    brush4VolumDataPointsColor = new SolidColorBrush { Color = Colors.Green };

    }

    Helpers.InvokePropertyChanged(PropertyChanged, this, "brush4VolumDataPointsColor");

    }

    }

    }

    }

    /////////////////////////////////////////

    <ResourceDictionary

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;

    xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit">

    <Style x:Key="StockColumnDataPoint" TargetType="chartingToolkit:ColumnDataPoint">

    <Setter Property="Background" Value="Blue"/>

    <Setter Property="BorderBrush" Value="Black"/>

    <Setter Property="BorderThickness" Value="1"/>

    <Setter Property="IsTabStop" Value="False"/>

    <Setter Property="Template">

    <Setter.Value>

    <ControlTemplate TargetType="chartingToolkit:ColumnDataPoint">

    <Border

    BorderBrush="{TemplateBinding BorderBrush}"

    BorderThickness="{TemplateBinding BorderThickness}"

    Opacity="0"

    x:Name="Root">

    <VisualStateManager.VisualStateGroups>

    <VisualStateGroup x:Name="CommonStates">

    <VisualStateGroup.Transitions>

    <VisualTransition GeneratedDuration="0:0:0.1"/>

    </VisualStateGroup.Transitions>

    <VisualState x:Name="Normal"/>

    <VisualState x:Name="MouseOver">

    <Storyboard>

    <DoubleAnimation

    Storyboard.TargetName="MouseOverHighlight"

    Storyboard.TargetProperty="Opacity"

    To="0.6"

    Duration="0"/>

    </Storyboard>

    </VisualState>

    </VisualStateGroup>

    <VisualStateGroup x:Name="SelectionStates">

    <VisualStateGroup.Transitions>

    <VisualTransition GeneratedDuration="0:0:0.1"/>

    </VisualStateGroup.Transitions>

    <VisualState x:Name="Unselected"/>

    <VisualState x:Name="Selected">

    <Storyboard>

    <DoubleAnimation

    Storyboard.TargetName="SelectionHighlight"

    Storyboard.TargetProperty="Opacity"

    To="0.6"

    Duration="0"/>

    </Storyboard>

    </VisualState>

    </VisualStateGroup>

    <VisualStateGroup x:Name="RevealStates">

    <VisualStateGroup.Transitions>

    <VisualTransition GeneratedDuration="0:0:0.5"/>

    </VisualStateGroup.Transitions>

    <VisualState x:Name="Shown">

    <Storyboard>

    <DoubleAnimation

    Storyboard.TargetName="Root"

    Storyboard.TargetProperty="Opacity"

    To="1"

    Duration="0"/>

    </Storyboard>

    </VisualState>

    <VisualState x:Name="Hidden">

    <Storyboard>

    <DoubleAnimation

    Storyboard.TargetName="Root"

    Storyboard.TargetProperty="Opacity"

    To="0"

    Duration="0"/>

    </Storyboard>

    </VisualState>

    </VisualStateGroup>

    </VisualStateManager.VisualStateGroups>

    <!–<Grid Background="{TemplateBinding background}">–>

    <Grid Background="{Binding brush4VolumDataPointsColor}">

    <Rectangle>

    <Rectangle.Fill>

    <LinearGradientBrush>

    <GradientStop

    Color="#ff80ffff"

    Offset="0"/>

    <GradientStop

    Color="#ff0000ff"

    Offset="1"/>

    </LinearGradientBrush>

    </Rectangle.Fill>

    </Rectangle>

    <Border

    BorderBrush="#ff00ffff"

    BorderThickness="1">

    <Border

    BorderBrush="#ff0000a0"

    BorderThickness="1"/>

    </Border>

    <Rectangle x:Name="SelectionHighlight" Fill="Red" Opacity="0"/>

    <Rectangle x:Name="MouseOverHighlight" Fill="White" Opacity="0"/>

    </Grid>

    <ToolTipService.ToolTip>

    <ContentControl Content="{TemplateBinding FormattedDependentValue}"/>

    </ToolTipService.ToolTip>

    </Border>

    </ControlTemplate>

    </Setter.Value>

    </Setter>

    </Style>

    </ResourceDictionary>

    //////////////////////////////////////

    <UserControl x:Class="INotifyPropertyChanged1.MainPage"

       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;

       xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;

       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;

    xmlns:visualizationToolkit="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"

    xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"

    xmlns:chartingPrimitivesToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting.Primitives;assembly=System.Windows.Controls.DataVisualization.Toolkit"

    mc:Ignorable="d"

    >

    <UserControl.Resources>

    <ResourceDictionary>

    <ResourceDictionary.MergedDictionaries>

    <ResourceDictionary Source="StockDataResourcesDictionary.xaml" />

    </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">

    <Grid.RowDefinitions>

    <RowDefinition/>

    <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

    <chartingToolkit:Chart

    x:Name="tstStockColumnDataPoint"

    HorizontalAlignment="Left"

    Width="1280"

    Height="640"

    Title="Chart Title"

    VerticalAlignment="Top"

    >

    <chartingToolkit:ColumnSeries

    DataPointStyle="{StaticResource StockColumnDataPoint}"

    IndependentValueBinding="{Binding datetime4StockDataGrabbed}"

    DependentValueBinding="{Binding dVolum}"

    IsSelectionEnabled="True"

    />

    <chartingToolkit:Chart.Axes>

    <chartingToolkit:LinearAxis

    Orientation="Y"

    MaxWidth="64"

    FontSize="8"

    ShowGridLines="True">

    </chartingToolkit:LinearAxis>

    <chartingToolkit:DateTimeAxis

    Orientation="X"

    Interval="15"

    IntervalType="Minutes"

    >

    </chartingToolkit:DateTimeAxis>

    </chartingToolkit:Chart.Axes>

    </chartingToolkit:Chart>

    <Button

               Content="Randomize Grades"

               Click="RandomizeGradesClick"

               Grid.Row="1"/>

    </Grid>

    </UserControl>

  7. Delay says:

    Crystal.ice,

    As I mentioned to you in email, this sample is part of my DataVisualizationDemos project and is kept up to date there with support for Silverlight 3, Silverlight 4, WPF 3.5, and WPF 4. If you could please have a look there, I think you’ll find a sample that runs on the latest bits that you can play around with.

    http://blogs.msdn.com/delay/archive/2009/11/30/two-birds-squared-silverlight-wpf-data-visualization-development-release-3-and-a-datavisualizationdemos-update.aspx

    If you’re still having trouble after that, let’s please continue this discussion in email because it’ll probably be a lot easier that way. 🙂

    Thanks!

  8. integragreg says:

    Can anyone provide details on a similar process that would allow you to customize the color of a LineDataPoint by binding the style to a template property? e.g., something like this:

    <Style TargetType="charting:LineDataPoint" x:Name="ldp1">

               <Setter Property="Background" Value="{TemplateBinding LineColor}" />

    WPF allows you to do this, but I don’t think that Silverlight does.

  9. Delay says:

    integragreg,

    I’m not sure I understand what you’re trying to do. The syntax you show will work in both Silverlight and WPF today if you add a Brush-typed LineColor property to the LineDataPoint class where TemplateBinding will look for it. But the *DataPoint classes aren’t really exposed to the user, so you’d probably want to control this with a property on the LineSeries class instead – in which case you’d probably want to use a normal Binding and the FindAncestor mode of RelativeSource. THAT will be WPF-only because FindAncestor isn’t supported in Silverlight. But it ought to work. 🙂

    Hope this helps!

  10. Brian says:

    I'm having trouble binding the Fill color for the Legend item.  Using SL4 with the April 2010 Toolkit.  I've tried several variations of Binding with no luck, using a named color works but obviously that's not useful.

  11. Brian says:

    After further testing it seems the Pie chart legend works without an issue but the Multichart legend does not.  I'm guessing there is something different about the Multichart's legend and the way it is bound.

  12. Delay says:

    Brian,

    The LegendItems of a PieSeries are each directly associated with the corresponding PieDataPoint – which is why they "just work". That's not possible with the other series where a single LegendItem represents [0..N] FooDataPoints. If you want to customize the background of a ColumnSeries's LegendItem, you should be able to do so either by setting a Style as ColumnSeries.DataPointStyle that includes a Setter for Background=Purple OR by setting a Style as ColumnSeries.LegendItemStyle that includes a custom Template (which can do whatever you want).

    It sounds like you may have tried that and gotten it to work successfully, but are having trouble changing from Purple to some Binding to a color defined by your model object? In that case, things are probably a little trickier because of the need to get the right source for the Binding passed into it. If you're setting this up in code, that shouldn't be too difficult – just set Binding.Source when you create the Binding. If you're doing it in XAML, you'll probably need to start with my SetterValueBindingHelper and then apply some cleverness. 🙂

    blogs.msdn.com/…/one-more-platform-difference-more-or-less-tamed-settervaluebindinghelper-makes-silverlight-setters-better.aspx

    I haven't tried this myself, but it seems like it should be possible. If you have trouble, let me know and I can add this scenario to my TODO list for blogging. Hope this helps!

  13. Brian says:

    I actually went about it in a different method, less effort involved.  🙂

    Since I had multiple charts on the page with a common legend I simply turned off the individual charts legends and made a common legend out of a listbox control.

  14. Delay says:

    Brian,

    Super – that's exactly one of the scenarios we tried to enable. 🙂 Glad to hear it's working out for you!

  15. Helen says:

    Hi, thanks for this tutorial.  It was very helpful.

    I was also wondering if anyone might know of how to color an area chart different colors, based on horizontal x-axis (time)?  (i.e. for time range 1, the area under the graph from spot A on the xaxis to spot B on the xaxis should be colored red, whereas for time range 2 (spot B to spot C), the area under the graph should be colored green).  Any ideas?  Thanks very much!

  16. Delay says:

    Helen,

    It's a neat idea, but something like that isn't natively supported by the current implementation. 🙁 What's more, I'm not sure I know of a great way to do this in general. However, if your scenario is a little flexible and not too wild, what you might be able to do (quite easily, in fact!) is use a Brush with a horizontal linear gradient for the Fill of the Area shape. That'd let you create something like a red->blue fade across the length of the area chart – though it wouldn't specifically let you tie the color chages to exact points on the axis.

    Hope this helps!

  17. how can i change the width of a column and animate it to an increasing column

  18. Delay says:

    Narender Rautela,

    Column width is automatic (though you could change the code if you wanted. Animating data changes is automatic (for data objects implementing INotifyPropertyChanged) as I discuss here: blogs.msdn.com/…/announcing-a-free-open-source-charting-solution-for-silverlight-silverlight-toolkit-released-today-at-pdc.aspx

    Hope this helps!

Comments are closed.