这是我尝试实现的图表/效果(来自Excel),其中彩色条/列显示实际值,并且以虚线界定的第二个条/列显示基准值:
这就是我从代码(下面)获得的内容:
如何让基准栏/列转移到实际(学校)值之后?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Web.UI.DataVisualization.Charting;
namespace ChartTest
{
class Program
{
private static Color _benchmarkColour = Color.LightGray;
private static System.Drawing.Font _graphFont = new System.Drawing.Font("Arial", 16f, FontStyle.Regular);
private static int chartWidth = 1600;
private static int chartHeight = 800;
private static ChartColorPalette chartPalette = ChartColorPalette.BrightPastel;
public class TimeSeriesDataPoint
{
public DateTime Date { get; set; }
public double? SchoolValue { get; set; }
public double? BenchmarkValue { get; set; }
}
public class BenchmarkDataPoint
{
public string Category { get; set; }
public double? SchoolValue { get; set; }
public double? BenchmarkValue { get; set; }
}
public class BenchmarkSeries
{
public string Name { get; set; }
public Color Color { get; set; }
public List<BenchmarkDataPoint> DataPoints { get; set; }
}
public class BenchmarkData
{
public List<BenchmarkSeries> Series { get; set; }
}
static void Main(string[] args)
{
var benchmarkData = new BenchmarkData { Series = new List<BenchmarkSeries>() };
var series1 = new BenchmarkSeries { Name = "2018H1", Color = Color.FromArgb(200, 64, 118, 196), DataPoints = new List<BenchmarkDataPoint>() };
series1.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 4", SchoolValue = 0.49d, BenchmarkValue = .65d });
series1.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 5", SchoolValue = 0.55d, BenchmarkValue = .68d });
series1.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 6", SchoolValue = 0.40d, BenchmarkValue = .55d });
series1.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 7", SchoolValue = 0.52d, BenchmarkValue = .56d });
benchmarkData.Series.Add(series1);
var series2 = new BenchmarkSeries { Name = "2018H2", Color = Color.FromArgb(200, 255, 192, 0), DataPoints = new List<BenchmarkDataPoint>() };
series2.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 4", SchoolValue = 0.35d, BenchmarkValue = .65d });
series2.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 5", SchoolValue = 0.53d, BenchmarkValue = .71d });
series2.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 6", SchoolValue = 0.43d, BenchmarkValue = .60d });
series2.DataPoints.Add(new BenchmarkDataPoint { Category = "Grade 7", SchoolValue = 0.52d, BenchmarkValue = .56d });
benchmarkData.Series.Add(series2);
var chart = GetBenchmarkChart(benchmarkData);
chart.SaveImage(@"C:\chart.jpg");
}
private static Chart GetBenchmarkChart(BenchmarkData benchmarkData)
{
var chart = new Chart();
chart.Width = chartWidth;
chart.Height = chartHeight;
chart.Palette = chartPalette;
foreach (var benchmarkSeries in benchmarkData.Series)
{
var series = new Series();
series.Name = benchmarkSeries.Name;
series.Color = benchmarkSeries.Color;
series.BorderColor = Color.FromArgb(255, benchmarkSeries.Color);
series.BorderWidth = 2;
var counter = 0;
foreach (var point in benchmarkSeries.DataPoints)
{
if (point.SchoolValue.HasValue) series.Points.Add(new DataPoint { YValues = new[] { point.SchoolValue.Value }, XValue = counter });
else series.Points.Add(new DataPoint { IsEmpty = true, XValue = counter });
series.Points[counter].AxisLabel = point.Category;
counter++;
}
chart.Series.Add(series);
var bmSeries = new Series();
bmSeries.YAxisType = AxisType.Secondary;
bmSeries.Name = benchmarkSeries.Name + ": Benchmark";
bmSeries.Color = Color.FromArgb(0, Color.Black);
bmSeries.BorderColor = Color.Gray;
bmSeries.BorderWidth = 2;
counter = 0;
foreach (var point in benchmarkSeries.DataPoints)
{
if (point.BenchmarkValue.HasValue) bmSeries.Points.Add(new DataPoint { YValues = new[] { point.BenchmarkValue.Value }, XValue = counter });
else bmSeries.Points.Add(new DataPoint { IsEmpty = true });
bmSeries.Points[counter].AxisLabel = point.Category;
counter++;
}
bmSeries.IsVisibleInLegend = false;
chart.Series.Add(bmSeries);
}
var legend = new Legend("Legend");
legend.Docking = Docking.Bottom;
legend.Alignment = StringAlignment.Center;
legend.Font = _graphFont;
chart.Legends.Add(legend);
var chartArea = new ChartArea();
chartArea.AxisX.MajorGrid.Enabled = false;
chartArea.AxisX.LabelAutoFitStyle = LabelAutoFitStyles.None;
chartArea.AxisX.LabelStyle.Font = _graphFont;
chartArea.AxisX.Interval = 1;
chartArea.AxisY.Minimum = 0;
chartArea.AxisY.Maximum = 1;
chartArea.AxisY.LabelStyle.Format = "{0:P0}";
chartArea.AxisY.MajorGrid.LineColor = Color.LightGray;
chartArea.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
chartArea.AxisY.MinorGrid.Enabled = false;
chartArea.AxisY.MinorTickMark.Enabled = false;
chartArea.AxisY2.Minimum = 0;
chartArea.AxisY2.Maximum = 1;
chartArea.AxisY2.Enabled = AxisEnabled.False;
chart.ChartAreas.Add(chartArea);
return chart;
}
}
}
答案 0 :(得分:0)
我使用StackedColumn
图表类型和计算4个组件得到了解决方法。它并不理想,我更愿意只是移动基准的x轴位置,但我还没有发现它是否可能。
这里是堆积的列代码(还没有处理空/空点):
private static Chart GetBenchmarkChartStacked(BenchmarkData benchmarkData)
{
var chart = new Chart();
chart.Width = chartWidth;
chart.Height = chartHeight;
chart.Palette = chartPalette;
var seriescounter = 0;
foreach(var series in benchmarkData.Series)
{
seriescounter++;
var exceededBenchmark = new Series()
{
ChartType = SeriesChartType.StackedColumn,
Color = series.Color,
BorderColor = series.Color,
BorderWidth = 2,
CustomProperties = "StackedGroupName=" + series.Name,
IsVisibleInLegend = false
};
var school = new Series()
{
ChartType = SeriesChartType.StackedColumn,
Color = series.Color,
BorderColor = series.Color,
BorderWidth = 2,
CustomProperties = "StackedGroupName=" + series.Name,
IsVisibleInLegend = true,
Name = series.Name
};
var schoolAndBenchmark = new Series()
{
ChartType = SeriesChartType.StackedColumn,
Color = series.Color,
BorderColor = Color.Gray,
BorderWidth = 2,
BorderDashStyle = ChartDashStyle.Dash,
CustomProperties = "StackedGroupName=" + series.Name,
IsVisibleInLegend = false
};
var toReachBenchmark = new Series()
{
ChartType = SeriesChartType.StackedColumn,
Color = Color.FromArgb(0, Color.Black),
BorderColor = Color.Gray,
BorderWidth = 2,
BorderDashStyle = ChartDashStyle.Dash,
CustomProperties = "StackedGroupName=" + series.Name,
IsVisibleInLegend = false
};
if (seriescounter == 1)
{
toReachBenchmark.IsVisibleInLegend = true;
toReachBenchmark.Name = "Benchmark";
}
for (var i = 0; i < series.DataPoints.Count; i++)
{
var schoolValue = series.DataPoints[i].SchoolValue;
var benchmarkValue = series.DataPoints[i].BenchmarkValue;
if (schoolValue <= benchmarkValue)
{
exceededBenchmark.Points.Add(new DataPoint { IsEmpty = true });
schoolAndBenchmark.Points.Add(new DataPoint { IsEmpty = true });
school.Points.AddY(schoolValue);
toReachBenchmark.Points.AddY(benchmarkValue - schoolValue);
}
else
{
exceededBenchmark.Points.AddY(schoolValue - benchmarkValue);
schoolAndBenchmark.Points.AddY(benchmarkValue);
toReachBenchmark.Points.Add(new DataPoint { IsEmpty = true });
school.Points.Add(new DataPoint { IsEmpty = true });
}
exceededBenchmark.Points[i].AxisLabel = series.DataPoints[i].Category;
schoolAndBenchmark.Points[i].AxisLabel = series.DataPoints[i].Category;
toReachBenchmark.Points[i].AxisLabel = series.DataPoints[i].Category;
school.Points[i].AxisLabel = series.DataPoints[i].Category;
}
chart.Series.Add(school);
chart.Series.Add(schoolAndBenchmark);
chart.Series.Add(exceededBenchmark);
chart.Series.Add(toReachBenchmark);
}
var legend = new Legend("Legend");
legend.Docking = Docking.Bottom;
legend.Alignment = StringAlignment.Center;
legend.Font = _graphFont;
chart.Legends.Add(legend);
var chartArea = new ChartArea();
chartArea.AxisX.MajorGrid.Enabled = false;
chartArea.AxisX.LabelAutoFitStyle = LabelAutoFitStyles.None;
chartArea.AxisX.LabelStyle.Font = _graphFont;
//chartArea.AxisX.Interval = 1;
chartArea.AxisY.Minimum = 0;
chartArea.AxisY.Maximum = 1;
chartArea.AxisY.LabelStyle.Format = "{0:P0}";
chartArea.AxisY.MajorGrid.LineColor = Color.LightGray;
chartArea.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
chartArea.AxisY.MinorGrid.Enabled = false;
chartArea.AxisY.MinorTickMark.Enabled = false;
chart.ChartAreas.Add(chartArea);
return chart;
}
这是结果图: