純 GDI+ 繪製雙數據序列柱狀圖,無需第三方控件,適合輕量級統計展示。

public Image Render(string title, int width, int height, DataTable chartTable) {
var bmp = new Bitmap(width, height);
using (var g = Graphics.FromImage(bmp)) {
g.Clear(Color.White);
// 邊界、空數據檢查...
// 計算最大值
float maxVal = 1;
foreach (DataRow dr in chartTable.Rows) {
maxVal = Math.Max(maxVal, Convert.ToSingle(dr[0]));
maxVal = Math.Max(maxVal, Convert.ToSingle(dr[1]));
}
// 柱寬計算:預留間距
float barWidth = (width - left) / (chartTable.Rows.Count * 3 + 1);
PointF origin = new PointF(left + barWidth, 0);
// 字體大小自適應
float topFontSize = barWidth / maxVal.ToString().Length;
topFontSize = Math.Clamp(topFontSize, 5, 2*top/3);
foreach (DataRow dr in chartTable.Rows) {
// 序列 1 柱狀(紅)
float h1 = Convert.ToSingle(dr[0]) * (height - 2*top) / maxVal;
origin.Y = height - h1 - top;
g.FillRectangle(Brushes.Red, origin.X, origin.Y, barWidth, h1);
g.DrawString(dr[0].ToString(), font, Brushes.Red, origin.X, origin.Y - ...);
origin.X += barWidth;
// 序列 2 柱狀(藍)
float h2 = Convert.ToSingle(dr[1]) * (height - 2*top) / maxVal;
origin.Y = height - h2 - top;
g.FillRectangle(Brushes.Blue, origin.X, origin.Y, barWidth, h2);
g.DrawString(dr[1].ToString(), font, Brushes.Blue, origin.X, origin.Y - ...);
origin.X += barWidth * 2; // 間距
}
// 座標軸、底部標籤(dr[2] 作為 X 軸標籤)
}
return bmp;
}
| 列索引 | 含義 |
|---|---|
| 0 | 序列 1 數值(紅柱) |
| 1 | 序列 2 數值(藍柱) |
| 2 | X 軸標籤(如月份、類別名) |