Messed Up 2-Line Chart

7 posts, 1 answers
  1. Jonathan
    Jonathan avatar
    37 posts
    Member since:
    Sep 2012

    Posted 15 Feb 2013 Link to this post

    Any idea why my chart looks like the attachment?
    My guess was that my list of x-axis values was out of numeric order but as far as I can tell it's not. 
    Notice that it only seems to be my second line that is wacky. I try to generate the x-axis values by combining the possible values from my first line with my second in case I don't have a full set of one or the other.

  2. Petar Kirov
    Admin
    Petar Kirov avatar
    425 posts

    Posted 20 Feb 2013 Link to this post

    Hi Jonathan,

    Probably this issue is related to the way you have set the series ItemMappings and if the data comes in sorted order.
    In order to help you, we will need to see your RadChart creation code (XAML and/or code behind). It would be best if you could provide a small project, so we can reproduce locally and find the source of the problem.

    Regards,
    Petar Kirov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Jonathan
    Jonathan avatar
    37 posts
    Member since:
    Sep 2012

    Posted 27 Feb 2013 Link to this post

    So I've continued to wrestle with this and now have the following simple test case that demonstrates what I think might be my problem.
    (I am using version 2012.3.1129.40)

    It seems that in some cases the graph handles unmatched x-axis data points but not in others. In this test case it seems that if the series with the most items is the one that determines the behaviour. That may not be accurate though in how the chart decides which series to base it's x-axis on. If you could clarify that would help me solve my problem in my real world scenario and not this contrived example. Maybe it uses the first series added as it's determining factor for how the x-axis behaves.

    In the attached Messed1 image you can see how the chart has placed Sept at the end of the chart instead of between Aug and Oct where it belongs. The code that created the data for this chart is pasted below: (note the first CreateData is missing Sept)

    private static List<ProductSales> CreateData()
    {
        List<ProductSales> ps = new List<ProductSales>();
        ps.Add(new ProductSales(154, 1, "Jan"));
        ps.Add(new ProductSales(138, 2, "Feb"));
        ps.Add(new ProductSales(143, 3, "Mar"));
        ps.Add(new ProductSales(120, 4, "April"));
        ps.Add(new ProductSales(135, 5, "May"));
        ps.Add(new ProductSales(125, 6, "June"));
        ps.Add(new ProductSales(179, 7, "July"));
        ps.Add(new ProductSales(170, 8, "Aug"));
        // persons.Add(new ProductSales(198, 9, "Sept"));
        ps.Add(new ProductSales(187, 10, "Oct"));
        ps.Add(new ProductSales(193, 11, "Nov"));
        ps.Add(new ProductSales(212, 12, "Dec"));
        return ps;
    }
     
    private static List<ProductSales> CreateData2()
    {
        List<ProductSales> ps = new List<ProductSales>();
        ps.Add(new ProductSales(234, 4, "April"));
        ps.Add(new ProductSales(165, 5, "May"));
        ps.Add(new ProductSales(155, 6, "June"));
        ps.Add(new ProductSales(129, 7, "July"));
        ps.Add(new ProductSales(130, 8, "Aug"));
        ps.Add(new ProductSales(158, 9, "Sept"));
        ps.Add(new ProductSales(197, 10, "Oct"));
        ps.Add(new ProductSales(123, 11, "Nov"));
        ps.Add(new ProductSales(242, 12, "Dec"));
        return ps;
    }

    In the Messed2Not image the graph behaves better and simply skips the missing Sept data in the second series. The code that creates this data is below:

    private static List<ProductSales> CreateData()
    {
        List<ProductSales> ps = new List<ProductSales>();
        ps.Add(new ProductSales(154, 1, "Jan"));
        ps.Add(new ProductSales(138, 2, "Feb"));
        ps.Add(new ProductSales(143, 3, "Mar"));
        ps.Add(new ProductSales(120, 4, "April"));
        ps.Add(new ProductSales(135, 5, "May"));
        ps.Add(new ProductSales(125, 6, "June"));
        ps.Add(new ProductSales(179, 7, "July"));
        ps.Add(new ProductSales(170, 8, "Aug"));
        ps.Add(new ProductSales(198, 9, "Sept"));
        ps.Add(new ProductSales(187, 10, "Oct"));
        ps.Add(new ProductSales(193, 11, "Nov"));
        ps.Add(new ProductSales(212, 12, "Dec"));
        return ps;
    }
     
    private static List<ProductSales> CreateData2()
    {
        List<ProductSales> ps = new List<ProductSales>();
        ps.Add(new ProductSales(234, 4, "April"));
        ps.Add(new ProductSales(165, 5, "May"));
        ps.Add(new ProductSales(155, 6, "June"));
        ps.Add(new ProductSales(129, 7, "July"));
        ps.Add(new ProductSales(130, 8, "Aug"));
        // ps.Add(new ProductSales(158, 9, "Sept"));
        ps.Add(new ProductSales(197, 10, "Oct"));
        ps.Add(new ProductSales(123, 11, "Nov"));
        ps.Add(new ProductSales(242, 12, "Dec"));
        return ps;
    }


    The code that generates the graph using this data is below:

    public void testChart(int chartWidth = 1050, int chartHeight = 550)
    {
        RadChart radChart = new RadChart();
        radChart.BeginInit();
     
        radChart.Width = chartWidth;
        radChart.Height = chartHeight;
        radChart.DefaultView.ChartArea.EnableAnimations = false;
     
        radChart.BorderThickness = new Thickness(0);
        radChart.Background = new SolidColorBrush(Colors.Transparent);
     
        // hide the legend
        radChart.DefaultView.ChartLegend.Visibility = Visibility.Collapsed;
     
        // Setup X-Axis
        AxisX xAxis = radChart.DefaultView.ChartArea.AxisX;
        xAxis.MinorTicksVisibility = Visibility.Collapsed;
        xAxis.MajorTicksVisibility = Visibility.Collapsed;
     
        SeriesMapping seriesMapping = new SeriesMapping();
        seriesMapping.LegendLabel = "Product Sales";
     
        // seriesMapping.SeriesDefinition = new LineSeriesDefinition();
     
        seriesMapping.SeriesDefinition = new AreaSeriesDefinition();
        seriesMapping.SeriesDefinition.Appearance.Fill = new System.Windows.Media.SolidColorBrush(Colors.LightBlue);
        seriesMapping.SeriesDefinition.Appearance.Fill.Opacity = .33;
     
        seriesMapping.ItemMappings.Add(new ItemMapping("MonthName", DataPointMember.XCategory));
        seriesMapping.ItemMappings.Add(new ItemMapping("Quantity", DataPointMember.YValue));
        seriesMapping.CollectionIndex = 0;
        radChart.SeriesMappings.Add(seriesMapping);
     
        CustomGridLine gridline = new CustomGridLine();
        gridline.XIntercept = 9;
        gridline.Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Silver);
        gridline.StrokeThickness = 1;
        radChart.DefaultView.ChartArea.Annotations.Add(gridline);
     
        gridline = new CustomGridLine();
        gridline.XIntercept = 5;
        gridline.Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Silver);
        gridline.StrokeThickness = 1;
        radChart.DefaultView.ChartArea.Annotations.Add(gridline);
     
     
        var brushConverter = new BrushConverter();
     
        var bbSetter = new Setter(
            TextBlock.FontSizeProperty,
            24.0);
     
        var style = new Style(typeof(TextBlock));
        style.Setters.Add(bbSetter);
     
        bbSetter = new Setter(TextBlock.ForegroundProperty, brushConverter.ConvertFromString("#FFDDDDDD"));
        style.Setters.Add(bbSetter);
     
        radChart.DefaultView.ChartArea.AxisY.AxisStyles.ItemLabelStyle = style;
        radChart.DefaultView.ChartArea.AxisX.AxisStyles.ItemLabelStyle = style;
     
        // SECOND SERIES
        SeriesMapping seriesMapping2 = new SeriesMapping();
        seriesMapping2.SeriesDefinition = new LineSeriesDefinition();
        seriesMapping2.ItemMappings.Add(new ItemMapping("MonthName", DataPointMember.XCategory));
        seriesMapping2.ItemMappings.Add(new ItemMapping("Quantity", DataPointMember.YValue));
        seriesMapping2.CollectionIndex = 1;
        radChart.SeriesMappings.Add(seriesMapping2);
     
        List<List<ProductSales>> dats = new List<List<ProductSales>>(2);
        dats.Add(CreateData());
        dats.Add(CreateData2());
     
        radChart.ItemsSource = dats;
     
        radChart.Measure(new System.Windows.Size(radChart.Width, radChart.Height));
        radChart.Arrange(new System.Windows.Rect(radChart.DesiredSize));
     
        radChart.EndInit();
     
        using (MemoryStream ms = new MemoryStream())
        {
            radChart.ExportToImage(ms);
            using (FileStream imgFile = File.OpenWrite(@"C:\Projects\BLFlowSVN\Yahoo\FinanceGraphs\temp\graphOutTest.png"))
            {
                ms.Position = 0;
                ms.CopyTo(imgFile);
            }
     
            ms.Dispose();
        }
    }


    Any suggestions on how to best handle this in situation where my comparing data series may not have exact matches for the x-axis points as demonstrated by my sample?
  5. Jonathan
    Jonathan avatar
    37 posts
    Member since:
    Sep 2012

    Posted 01 Mar 2013 Link to this post

    So I have come up with a solution that seems to be working for me. If there's a better way I'd still like to know.

    I added an invisible series to the chart that has all the possible values from the 2 sets of data so that it no longer matters if one set has more or less because the master series that I use to generate my labels has all the possible x-values from both. I made it invisible by setting the line color to Transparent. I add this series as the very first series to the radChart.SeriesMappings. In my limited testing the results are good and the performance is still good.
  6. Jonathan
    Jonathan avatar
    37 posts
    Member since:
    Sep 2012

    Posted 15 Mar 2013 Link to this post

    I've also just discovered that if I have more datapoints then the value set in radChart.SamplingSettings.SamplingThreshold then my chart also gets really messed up. So for anyone else who happens along and reads this - maybe this will be a tip that will fix your problem.
  7. Answer
    Petar Kirov
    Admin
    Petar Kirov avatar
    425 posts

    Posted 20 Mar 2013 Link to this post

    Hi Jonathan,

    When RadChart is in categorical mode (i.e. its SeriesMappings use XCategory ItemMapping instead of XValue) it does not try to sort the xcategory values is any way - to the control they are just set of strings. RadChart positions them on the axis in the order they occur - first the xcategories from the first series then the new xcategories from the second and so on. If some of the series do not have data point(s) for a given category, you can use one of the following solutions:
    • Add data points with null value for the xcateogies you do not have information and set the empty behavior of the series to Gap
    • Add a transparent placeholder series containing all the possible categories, before the the other series.
    We have identified that this is a common problem especially when the categories represent DateTime information and that is why have introduced a solution to this in our newer charting solution - RadCartesianChart (part of RadChartView) - DateTimeCategoricalAxis, which allows data points to be grouped by a user-defined date-time component (Year, Month, Day, etc.) and then the groups are sorted chronologically. 

    If the number of data points is above the SamplingThreshold (by default 200), RadChart will combine groups of data points into a single one to improve readability and performance. If this is unwanted, you can the SamplingThreshold to 0 to disable it.

    I hope this helps.

    All the best,
    Petar Kirov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  8. Jonathan
    Jonathan avatar
    37 posts
    Member since:
    Sep 2012

    Posted 20 Mar 2013 Link to this post

    Thank you for these explanations. This is helpful and confirms the behaviour I have seen. 
Back to Top
UI for WPF is Visual Studio 2017 Ready