MS 图表数据值标签

MS Chart Data Value Labels

我正在 MVC 中使用 C# 通过 MS-Chart 构建一个 "Stacked Column" 图表。我的图表有 3 个系列。我试图让每个系列的数据值标签显示在 X 轴下方,而不是显示在每一列上。

我一直在网上搜索,希望能找到一些指向这种类似布局的指针,但 none 已经找到了 2 天。

有人可以指点一下如何完成数据值标签排列的相同位置吗?

这是最简单的解决方案。它的样式不是很好,但只需要几行:

var months = new[] { "Jan", "Feb", "Mar", "Apr", "May", 
                     "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

for (int i = 0; i < pointCount; i++)
{
    double sum = 0;
    string label = "";
    for (int j = seriesCount - 1; j >= 0;  j--)
    {
        sum += chart.Series[j].Points[i].YValues[0];
        label += "\n" + +chart.Series[j].Points[i].YValues[0] ;
    }
    chart.Series[0].Points[i].AxisLabel = months[i] + "\n"  + sum + label;
}

这会为第一个 Series 的每个 DataPoint 添加一个标签字符串。请注意,每个点只能显示一个这样的标签;稍后 Series 的标签将被忽略。

为标签的月份部分使用合适的计数器和任何你想要的东西。

要获得更好的外观,例如粗体字或彩色背景,您需要做更多的工作。

请注意,标签中的数字和系列中的数字是反向堆叠的,因此内部循环是向后的。

这适用于任意数量的系列。

这是使用 PostPaint 事件的变体:

private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
    if (chart1.Series[0].Points.Count <= 0) return;

    Graphics g = e.ChartGraphics.Graphics;
    ChartArea ca = chart1.ChartAreas[0];
    Rectangle rip = Rectangle.Round(InnerPlotPositionClientRectangle(chart1, ca));

    StringFormat fmt = new StringFormat()
    { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };

    int cols = chart1.Series[0].Points.Count;
    int sCount = chart1.Series.Count;
    int w = rip.Width / (cols + 1);  // there is ca. 1/2 column gap to the sides

    for (int i = 0; i < cols; i++)
    {
        List<string> s = (List<string>)(chart1.Series[0].Points[i].Tag);
        for (int j = 0; j < s.Count; j++)
        {
            // change magic numbers with your font!
            Rectangle r = new Rectangle(rip.Left + i * w + w / 2, 
                                        rip.Bottom + 5 + 25 * j, w, 25);
            // 1st row: header, 2nd row sum, rest moved up by and reversed
            using (SolidBrush brush = new SolidBrush(j == 0 ? Color.Transparent
                : j == 1 ? Color.Gray : chart1.Series[sCount + 1 - j].Color))
                g.FillRectangle(brush, r);
            g.DrawRectangle(Pens.White, r);
            g.DrawString(s[j], ca.AxisX.LabelStyle.Font, Brushes.White, r, fmt);
        }
    }
}

它使用相同的例程来收集标签字符串,但不是设置 AxisLabels,而是将它们添加到 DataPoints:

Tags
    string l =  months[i] + "\n"  + sum + label;
    chart.Series[0].Points[i].Tag = l.Split('\n').ToList();

图表样式几乎占据了大部分代码:

chart.BackColor = Color.DarkSlateGray;
ChartArea ca = chart.ChartAreas[0];
chart.Legends[0].Alignment = StringAlignment.Center;
chart.Legends[0].Docking = Docking.Top;
chart.Legends[0].BackColor =  chart.BackColor;
chart.Legends[0].ForeColor = Color.White;

Legend L = chart.Legends[0];
L.CustomItems.Add(Color.Silver, "Sum");

ca.BackColor = Color.LightSteelBlue;
ca.Position = new ElementPosition(2, 8, 93, 70);  // make room

ca.Area3DStyle.Enable3D = true;
ca.Area3DStyle.PointDepth = 25;
ca.Area3DStyle.WallWidth = 0;

ca.AxisX.MajorGrid.Enabled = false;
ca.AxisY.MajorGrid.LineColor = Color.White;
ca.AxisY.LineColor = Color.White;
ca.AxisY.LabelStyle.ForeColor = Color.White;
ca.AxisY.MajorTickMark.LineColor = Color.White;
ca.AxisX.LabelStyle.Enabled = false;
ca.AxisX.LineColor = Color.White;
ca.AxisX.MajorTickMark.Enabled = false;

使用 Colors 创建 Series 后,您需要应用它们,以便可以在代码中访问它们:

chart1.ApplyPaletteColors();

Series 的漂亮圆角列是由 CustomProperty

创建的
s.SetCustomProperty("DrawingStyle", "Cylinder");

更多细节:

chart.Series[1].Color = Color.Crimson;
chart.Series[0].LegendText = "Hobbits";
..

更新:您需要包含我的其他一些帖子中的两个函数 InnerPlotPositionClientRectangleChartAreaClientRectangle,例如 here or here!

为了做到这一点 work in ASP 你在 PageLoad:

中连接事件
chart1.PostPaint += new EventHandler<ChartPaintEventArgs>(chart1_PostPaint);