developer
developer

Reputation: 1675

Overlap Stacked Area Chart in WinForms

I am trying to overlap a stacked area chart on an existing chart in a WinForm application (using System.Windows.Forms.DataVisualization.Charting library).

enter image description here

As per the above screenshot, the green colored stacked area chart should be at the highlighted (yellow) color line. However, currently the code creates it on top of the existing stacked area chart (blue).

How can I change it such that the blue and green color charts overlap?

Code:

private void DrawChart()
    {
        var dataTable = new DataTable();
        dataTable.Columns.Add("Year");
        dataTable.Columns.Add("2020");
        dataTable.Columns.Add("2021");
        dataTable.Columns.Add("2022");
        dataTable.Columns.Add("2023");
        dataTable.Columns.Add("2024");

        var dr = dataTable.NewRow();
        dr = dataTable.NewRow();
        dr["Year"] = "Stacked Area 1";
        dr["2020"] = 20000;
        dr["2021"] = 60000;
        dr["2022"] = 130000;
        dr["2023"] = 190000;
        dr["2024"] = 220000;
        dataTable.Rows.Add(dr);

        dr = dataTable.NewRow();
        dr["Year"] = "Stacked Area 2";
        dr["2020"] = 30000;
        dr["2021"] = 70000;
        dr["2022"] = 140000;
        dr["2023"] = 200000;
        dr["2024"] = 230000;
        dataTable.Rows.Add(dr);


        dr = dataTable.NewRow();

        dr["Year"] = "Overlapping Stacked Area 1";
        dr["2020"] = 10000;
        dr["2021"] = 50000;
        dr["2022"] = 120000;
        dr["2023"] = 180000;
        dr["2024"] = 210000;
        dataTable.Rows.Add(dr);



        dr = dataTable.NewRow();
        dr["Year"] = "Overlapping Stacked Area 2";
        dr["2020"] = 15000;
        dr["2021"] = 60000;
        dr["2022"] = 130000;
        dr["2023"] = 190000;
        dr["2024"] = 220000;
        dataTable.Rows.Add(dr);


        chart.ChartAreas["Default"].AxisX.Crossing = 0;
        chart.ChartAreas["Default"].AxisY.Crossing = 0;
        chart.Visible = true;


        foreach (DataRow row in dataTable.Rows)
        {
            string seriesName = row["Year"].ToString();

            if (chart.Series.FindByName(seriesName) == null)
            {
                chart.Series.Add(seriesName);
                switch (seriesName)
                {
                    case "Stacked Area 1":
                        chart.Series[seriesName].ChartType = SeriesChartType.StackedArea;
                        chart.Series[seriesName].Color = Color.Transparent;
                        chart.Series[seriesName].BorderDashStyle = ChartDashStyle.Dot;
                        chart.Series[seriesName].BorderWidth = 2;
                        chart.Series[seriesName].BorderColor = Color.Black;
                        break;
                    case "Stacked Area 2":
                        chart.Series[seriesName].ChartType = SeriesChartType.StackedArea;
                        chart.Series[seriesName].Color = Color.LightBlue;
                        chart.Series[seriesName].BorderDashStyle = ChartDashStyle.Dot;
                        chart.Series[seriesName].BorderWidth = 2;
                        chart.Series[seriesName].BorderColor = Color.Black;
                        break;
                    case "Overlapping Stacked Area 1":
                        chart.Series[seriesName].ChartType = SeriesChartType.StackedArea;
                        chart.Series[seriesName].SetDefault(true);
                        chart.Series[seriesName].Color = Color.Transparent;
                        chart.Series[seriesName].BorderDashStyle = ChartDashStyle.Dot;
                        chart.Series[seriesName].BorderWidth = 2;
                        chart.Series[seriesName].BorderColor = Color.FromArgb(100, Color.Green);

                        break;
                    case "Overlapping Stacked Area 2":
                        chart.Series[seriesName].ChartType = SeriesChartType.StackedArea;
                        chart.Series[seriesName].SetDefault(true);
                        chart.Series[seriesName].Color = Color.FromArgb(100, Color.Green);
                        chart.Series[seriesName].BorderDashStyle = ChartDashStyle.Dot;
                        chart.Series[seriesName].BorderWidth = 2;
                        chart.Series[seriesName].BorderColor = Color.FromArgb(100, Color.Green);
                        break;
                }
            }

            chart.Series[seriesName].Points.Clear();
            var years = dataTable.Columns.Count;

            for (int i = 1; i < years; i++)
            {
                string columnName = dataTable.Columns[i].ColumnName;
                if (row[columnName] != null && !String.IsNullOrEmpty(row[columnName].ToString()))
                {
                    var val = Convert.ToInt64(row[columnName].ToString());
                    chart.Series[seriesName].Points.AddXY(columnName, val);

                }
            }
        }
    }

Upvotes: 0

Views: 385

Answers (1)

milespossing
milespossing

Reputation: 130

There are a number of ways to solve this, but I'd say that the best place to start would be changing the type of Series from stacked to "Range". If you look into that series type it definitely seems to be what you're looking for. I've created some example code adapted from your original code. I've used tuples because I didn't want to spend a massive amount of time doing this, but I definitely wouldn't recommend using them for this.

    private void DrawChart()
    {
        var dataTable = new DataTable();
        dataTable.Columns.Add("Year");
        dataTable.Columns.Add("2020",typeof(Tuple<int,int>));
        dataTable.Columns.Add("2021",typeof(Tuple<int,int>));
        dataTable.Columns.Add("2022",typeof(Tuple<int,int>));
        dataTable.Columns.Add("2023",typeof(Tuple<int,int>));
        dataTable.Columns.Add("2024", typeof(Tuple<int, int>));

        var dr = dataTable.NewRow();
        dr = dataTable.NewRow();
        dr["Year"] = "Range 1";
        dr["2020"] = new Tuple<int,int>(20000, 30000);
        dr["2021"] = new Tuple<int,int>(60000, 70000);
        dr["2022"] = new Tuple<int,int>(130000, 140000);
        dr["2023"] = new Tuple<int,int>(190000, 200000);
        dr["2024"] = new Tuple<int,int>(220000, 230000);
        dataTable.Rows.Add(dr);

        dr = dataTable.NewRow();

        dr["Year"] = "Range 2";
        dr["2020"] = new Tuple<int,int>(10000, 25000);
        dr["2021"] = new Tuple<int,int>(50000, 90000);
        dr["2022"] = new Tuple<int,int>(120000, 130000);
        dr["2023"] = new Tuple<int,int>(180000, 210000);
        dr["2024"] = new Tuple<int,int>(210000, 220000);
        dataTable.Rows.Add(dr);

        chart.ChartAreas["Default"].AxisX.Crossing = 0;
        chart.ChartAreas["Default"].AxisY.Crossing = 0;
        chart.Visible = true;


        foreach (DataRow row in dataTable.Rows)
        {
            string seriesName = row["Year"].ToString();
            Series series = null;
            if (chart.Series.FindByName(seriesName) == null)
            {
                series = chart.Series.Add(seriesName);
                switch (seriesName)
                {
                    case "Range 1":
                        chart.Series[seriesName].ChartType = SeriesChartType.Range;
                        chart.Series[seriesName].Color = Color.FromArgb(100,Color.LightBlue);
                        chart.Series[seriesName].BorderDashStyle = ChartDashStyle.Dot;
                        chart.Series[seriesName].BorderWidth = 2;
                        chart.Series[seriesName].BorderColor = Color.Black;
                        break;
                    case "Range 2":
                        chart.Series[seriesName].ChartType = SeriesChartType.Range;
                        chart.Series[seriesName].SetDefault(true);
                        chart.Series[seriesName].Color = Color.FromArgb(100, Color.Green);
                        chart.Series[seriesName].BorderDashStyle = ChartDashStyle.Dot;
                        chart.Series[seriesName].BorderWidth = 2;
                        chart.Series[seriesName].BorderColor = Color.FromArgb(100, Color.Green);
                        break;
                }
            }
            if (series == null) continue;

            var years = dataTable.Columns.Count;
            for (int i = 1; i < years; i++)
            {
                string columnName = dataTable.Columns[i].ColumnName;
                if (row[columnName] != null && !String.IsNullOrEmpty(row[columnName].ToString()))
                {
                    var val = (Tuple<int,int>) row[columnName];
                    series.Points.AddXY(columnName, val.Item1,val.Item2);
                }
            }

        }
    }

Upvotes: 1

Related Questions