首页 > 解决方案 > WinForms中的重叠堆积面积图

问题描述

我正在尝试在 WinForm 应用程序中的现有图表上重叠堆积面积图(使用 System.Windows.Forms.DataVisualization.Charting 库)。

在此处输入图像描述

根据上面的屏幕截图,绿色堆积面积图应位于突出显示(黄色)的颜色线上。但是,当前代码在现有堆积面积图(蓝色)之上创建它。

如何更改它以使蓝色和绿色图表重叠?

代码:

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);

                }
            }
        }
    }

标签: winformschartsdata-visualization

解决方案


有很多方法可以解决这个问题,但我想说最好的起点是将系列的类型从堆叠更改为“范围”。如果您查看该系列类型,它肯定似乎是您正在寻找的东西。我创建了一些根据您的原始代码改编的示例代码。我使用元组是因为我不想花费大量时间来做这件事,但我绝对不建议为此使用它们。

    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);
                }
            }

        }
    }

推荐阅读