Chart LineSeries color is not unique when you set the DataPointStyle

Jul 3, 2009 at 8:51 PM

 

I have been working with the chart and found a sample that would allow me to style the DataPoints so I can have a little more detail in my tool tip (Below you will see my style), once I set the style for the DataPoints on the LineSeries all of the line series then have the same background color.  So my question is how do I style the DataPoints and still have a unique color between series's?  Any help would be greatly appreciated.

            <Style x:Key="ToolTipDataPointStyle" TargetType="chartTk:LineDataPoint">
                <Setter Property="Background" Value="LightGray"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="chartTk:LineDataPoint">
                            <Grid x:Name="Root" Opacity="1">
                                <ToolTipService.ToolTip>
                                    <StackPanel Margin="2,2,2,2">
                                        <ContentControl Content="{Binding Path=Tag}" ContentStringFormat="Date Recorded: {0}"/>
                                        <ContentControl Content="{Binding Path=Y}" ContentStringFormat="Value: {0}"/>
                                    </StackPanel>
                                </ToolTipService.ToolTip>
                                <Ellipse StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>


I thought I had found a way around this by creating a LineSeries Style and generating a random color and then partying on, this works fine except that the data points are still the same color and the legend is worth loss because all items in the legend have the same
color as the data points. My line Series style is below

<Style x:Key="test" TargetType="chartTk:LineSeries">
                <Setter Property="IsTabStop" Value="False" />
                <Setter Property="PolylineStyle">
                    <Setter.Value>
                        <Style TargetType="Polyline">
                            <Setter Property="StrokeThickness" Value="2" />
                            <Setter Property="StrokeMiterLimit" Value="1" />
                        </Style>
                    </Setter.Value>
                </Setter>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="chartTk:LineSeries">
                            <Canvas x:Name="PlotArea">
                                <Polyline Points="{TemplateBinding Points}" Stroke="{Binding Converter={StaticResource ColorConverter}, ConverterParameter={TemplateBinding Background}}" Style="{TemplateBinding PolylineStyle}" />
                            </Canvas>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
and the converter that is referenced

object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      Random r = new Random(Counter++);
      Color rand = Color.FromRgb((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255));
      SolidColorBrush brush = new SolidColorBrush(rand);

      return brush;      
    }

and the code behind that is creating the chart

private void BuildNormalGraph(Chart chart, Dictionary<string, List<ChartData>> dict)
    {
      chart.Series.Clear();

      foreach (var item in dict)
      {
        LineSeries ls = new LineSeries();

        ls.DependentValueBinding = new Binding("Y");
        ls.IndependentValueBinding = new Binding("Tag");        

        ls.DataPointStyle = this.layout.FindResource("ToolTipDataPointStyle") as Style;

        ls.Style = this.layout.FindResource("test") as Style;

        ls.Title = item.Key;

        List<MyPoint> points = new List<MyPoint>();

        foreach (var val in item.Value)
        {
          MyPoint point = new MyPoint();

          point.Y = (double)val.ValueY;
          point.Tag = val.ValueX;

          points.Add(point);
        }

        ls.ItemsSource = points;

        if (points.Count > 0)
        {
          chart.Series.Add(ls);
        }
      }
    }

 

Coordinator
Jul 7, 2009 at 7:30 AM

I believe I answer these questions in the following blog post I did a while back:

http://blogs.msdn.com/delay/archive/2009/05/19/chart-tweaking-made-easy-how-to-make-four-simple-color-tooltip-changes-with-silverlight-wpf-charting.aspx

Hope this helps!

Jul 7, 2009 at 9:39 PM

I have looked at the samples on your blogs and tried to implement them, I still get the same results.  It looks like it works fine with column and pie charts but for some reason line series are not working. 

I don't know if you tried implementing my code but you should be able to reproduce the problem.

Thanks for the help

Jul 7, 2009 at 9:47 PM

I have created an image to show what I am talking about I hope this helps

http://s849.photobucket.com/albums/ab57/masontwo23/?action=view&current=graphTest.png

Coordinator
Jul 8, 2009 at 8:00 AM

Thanks for the image. So as I understand it, you want two or more LineSeries, each with their own custom colors, right? If so, here's a simple XAML-only example I put together to do just that. You can paste it right into my ChartBuilder to see it running live.

If I'm still missing the point, please tell me what it is that the sample below isn't doing that you want.

Thanks!!

<Grid xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:datavis="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit" xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" xmlns:utility="clr-namespace:Utility;assembly=ChartBuilder" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <charting:Chart>
    <charting:Chart.Series>
      <charting:LineSeries
        IndependentValuePath="X"
        DependentValuePath="Y">
        <charting:LineSeries.ItemsSource>
          <PointCollection>
            <Point X="1" Y="1"/>
            <Point X="2" Y="2"/>
            <Point X="3" Y="3"/>
          </PointCollection>
        </charting:LineSeries.ItemsSource>
        <charting:LineSeries.DataPointStyle>
            <Style TargetType="charting:LineDataPoint">
                <Setter Property="Background" Value="Green"/>
            </Style>
        </charting:LineSeries.DataPointStyle>
      </charting:LineSeries>
      <charting:LineSeries
        IndependentValuePath="X"
        DependentValuePath="Y">
        <charting:LineSeries.ItemsSource>
          <PointCollection>
            <Point X="1" Y="2"/>
            <Point X="2" Y="3"/>
            <Point X="3" Y="4"/>
          </PointCollection>
        </charting:LineSeries.ItemsSource>
        <charting:LineSeries.DataPointStyle>
            <Style TargetType="charting:LineDataPoint">
                <Setter Property="Background" Value="Red"/>
            </Style>
        </charting:LineSeries.DataPointStyle>
      </charting:LineSeries>
    </charting:Chart.Series>
  </charting:Chart>
</Grid>

Jul 8, 2009 at 4:35 PM

Your code is what I would like except that I want to create the chart and line series from the code behind in C#, I would also like to restyle the DataPoint ToolTip.  I was able to implement your xaml and change it to C# to work in my code behind the link below shows the result of that.

http://s849.photobucket.com/albums/ab57/masontwo23/?action=view&current=david_example.png&t=1247066489333

Code similar to your xaml.  I need to be able to graph an unknown number of series so hard coding in xaml or code is not going to work for me, for this example it will work okay.

 

      LineSeries ls = new LineSeries();

      ls.IndependentValuePath = "X";
      ls.DependentValuePath = "Y";

      List<Point> points = new List<Point>();

      points.Add(new Point() { X = 1, Y = 1 });
      points.Add(new Point() { X = 2, Y = 2 });
      points.Add(new Point() { X = 3, Y = 3 });

      ls.ItemsSource = points;

      Style s = new Style(typeof(LineDataPoint));
      s.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, Brushes.Green));

      ls.DataPointStyle = s;

      chart.Series.Add(ls);

      ls = new LineSeries();

      ls.IndependentValuePath = "X";
      ls.DependentValuePath = "Y";

      points = new List<Point>();

      points.Add(new Point() { X = 1, Y = 2 });
      points.Add(new Point() { X = 2, Y = 3 });
      points.Add(new Point() { X = 3, Y = 4 });

      ls.ItemsSource = points;

      s = new Style(typeof(LineDataPoint));
      s.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, Brushes.Red));

      ls.DataPointStyle = s;

      chart.Series.Add(ls);

Below is what I really want, but the datapoints are the wrong color along with the legend items

http://s849.photobucket.com/albums/ab57/masontwo23/?action=view&current=masontwo_datapoints.png

Below is the code used to create the chart in the image

C# Code behind --

foreach (var item in dict)
      {
        LineSeries ls = new LineSeries();

        ls.DependentValueBinding = new Binding("Y");
        ls.IndependentValueBinding = new Binding("Tag");

        ls.DataPointStyle = this.layout.FindResource("ToolTipDataPointStyle") as Style;

        ls.Style = this.layout.FindResource("test") as Style;
        //ls.DataPointStyle = this.layout.FindResource("MyLineDataPointStyle") as Style;

        //ColorConverter cc = new ColorConverter();

        ls.Background = Brushes.Blue;

        ls.Title = item.Key;

        List<MyPoint> points = new List<MyPoint>();

        foreach (var val in item.Value)
        {
          MyPoint point = new MyPoint();

          point.Y = (double)val.ValueY;
          point.Tag = val.ValueX;

          points.Add(point);
        }

        ls.ItemsSource = points;

        if (points.Count > 0)
        {
          chart.Series.Add(ls);
        }
      }

--ToolTipDataPointStyle from xaml

<Style x:Key="ToolTipDataPointStyle" TargetType="chartTk:LineDataPoint">                
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartTk:LineDataPoint">
<Grid x:Name="Root" Opacity="1">
<ToolTipService.ToolTip>
<StackPanel Margin="2,2,2,2">
<ContentControl Content="{Binding Path=Tag}" ContentStringFormat="Date Recorded: {0}"/>
<ContentControl Content="{Binding Path=Y}" ContentStringFormat="Value: {0}"/>
</StackPanel>
</ToolTipService.ToolTip>
<Ellipse StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


-- test style from xaml
<Style x:Key="test" TargetType="chartTk:LineSeries">
                <Setter Property="IsTabStop" Value="False" />
                <Setter Property="PolylineStyle">
                    <Setter.Value>
                        <Style TargetType="Polyline">
                            <Setter Property="StrokeThickness" Value="2" />
                            <Setter Property="StrokeMiterLimit" Value="1" />
                        </Style>
                    </Setter.Value>
                </Setter>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="chartTk:LineSeries">
                            <Canvas x:Name="PlotArea">                                
                                <Polyline Points="{TemplateBinding Points}" Stroke="{Binding Converter={StaticResource ColorConverter}}" Style="{TemplateBinding PolylineStyle}" />
                            </Canvas>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

-- ColorConverter from C#

object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      Random r = new Random(Counter++);
      Color rand = Color.FromRgb((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255));
      SolidColorBrush brush = new SolidColorBrush(rand);

      return brush;      
    }

Thanks for any help

Justin




 

 

Coordinator
Jul 8, 2009 at 10:09 PM

Here's a complete example that does what you're asking for using the custom ToolTip style you've provided - in code this time:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.DataVisualization.Charting;
using System.Windows.Media;

namespace WpfApplication12
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            var c = new Chart();
            var ttdps = (Style)LayoutRoot.Resources["ToolTipDataPointStyle"];
            var adps = new Style(typeof(LineDataPoint), ttdps);
            adps.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = new SolidColorBrush(Colors.Red) });
            var bdps = new Style(typeof(LineDataPoint), ttdps);
            bdps.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = new SolidColorBrush(Colors.Green) });

            var a = new LineSeries();
            a.IndependentValuePath = "X";
            a.DependentValuePath = "Y";
            a.DataPointStyle = adps;
            var ap = new PointCollection();
            ap.Add(new Point(1, 1));
            ap.Add(new Point(2, 2));
            ap.Add(new Point(3, 3));
            a.ItemsSource = ap;
            c.Series.Add(a);

            var b = new LineSeries();
            b.IndependentValuePath = "X";
            b.DependentValuePath = "Y";
            b.DataPointStyle = bdps;
            var bp = new PointCollection();
            bp.Add(new Point(1, 2));
            bp.Add(new Point(2, 3));
            bp.Add(new Point(3, 4));
            b.ItemsSource = bp;
            c.Series.Add(b);

            LayoutRoot.Children.Add(c);
        }
    }
}
<Window x:Class="WpfApplication12.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:chartTk="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit">
    <Grid x:Name="LayoutRoot">
        <Grid.Resources>
            <Style x:Key="ToolTipDataPointStyle" TargetType="chartTk:LineDataPoint">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="chartTk:LineDataPoint">
                            <Grid x:Name="Root" Opacity="1">
                                <ToolTipService.ToolTip>
                                    <StackPanel Margin="2,2,2,2">
                                        <ContentControl Content="{Binding Path=Tag}" ContentStringFormat="Date Recorded: {0}"/>
                                        <ContentControl Content="{Binding Path=Y}" ContentStringFormat="Value: {0}"/>
                                    </StackPanel>
                                </ToolTipService.ToolTip>
                                <Ellipse StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Grid.Resources>
    </Grid>
</Window>
Jul 8, 2009 at 10:19 PM

That worked great.  Thank you very much!!!

I am still a novice at WPF, thank you again for helping me.

Nov 13, 2009 at 7:54 PM

Very helpful, thanks guys.  I was wondering where the default line series colors come from since they look pretty good to me?  I was hoping to do something similar here and modify the tooltip, but continue using the default colors.

 

I was also wondering if there's a way to add some effects to the lines series, such as a drop shadow?