【WinForm UI控件系列】BarPlot柱状图控件

前言:c# winform UI控件系列,做不到最好用,但愿是更好用!

一、效果图





二、使用说明

BarPlotEx 柱状图控件

控件简介

BarPlotEx 是一个功能强大的柱状图控件,参考 ScottPlot 设计,支持亮暗主题切换、色彩模式、值标签显示、对比柱状图、标题设置、坐标轴箭头、网格线样式和图例位置控制。

主要特性

  • 简单易用:参考 ScottPlot API,几行代码即可创建专业图表
  • 亮暗主题:自动适配亮色/暗色主题,也可独立设置颜色
  • 色彩模式:支持 Primary/Success/Warning/Error 等功能色
  • 值标签显示:支持在柱子顶部显示数值标签
  • 对比柱状图:支持多组数据并排对比显示
  • 边距控制:支持像素边距和百分比边距(参考 ScottPlot Axes.Margins)
  • 图例支持:可显示多系列数据的图例说明,支持背景、边框和位置控制
  • 标题支持:支持设置图表标题,可控制位置、大小、颜色和粗细
  • 坐标轴箭头:支持显示X轴和Y轴箭头
  • 网格线样式:支持水平/垂直网格线,可调整宽度、样式和颜色
  • 背景图支持:支持设置背景图片和背景色

基本使用

简单柱状图

csharp 复制代码
// 创建柱状图控件
var barPlot = new BarPlotEx
{
    Dock = DockStyle.Fill,
    ColorType = ColorType.Primary
};

// 添加数据
double[] values = { 5, 10, 7, 13 };
barPlot.AddBars(values);

// 设置底部边距为0,使柱子贴底
barPlot.MarginBottomPercent = 0;

// 刷新显示
barPlot.RefreshPlot();

this.Controls.Add(barPlot);

### 带标签的柱状图(数组方式)

```csharp
double[] values = { 5, 10, 7, 13 };
string[] labels = { "Q1", "Q2", "Q3", "Q4" };

// 一次性传入数值和标签
var series = barPlot.AddBars(values, labels, "销售额");

barPlot.SetMarginPercent(bottom: 0, top: 0.1);
barPlot.RefreshPlot();

带X轴标签和值标签的柱状图(完整数组方式)

csharp 复制代码
double[] values = { 5, 10, 7, 13 };
string[] xLabels = { "Q1", "Q2", "Q3", "Q4" };
string[] valueLabels = { "5万", "10万", "7万", "13万" };

// 一次性传入数值、X轴标签和值标签
var series = barPlot.AddBars(values, xLabels, valueLabels, "销售额");

// 显示值标签
barPlot.ShowValueLabels = true;

barPlot.SetMarginPercent(bottom: 0, top: 0.15);
barPlot.RefreshPlot();

带X轴标签,自动显示数值标签

csharp 复制代码
double[] values = { 25, 40, 35, 55 };
string[] xLabels = { "A产品", "B产品", "C产品", "D产品" };

// 自动将数值转为字符串作为值标签显示
var series = barPlot.AddBars(values, xLabels, "销售额", showValueLabels: true);

// 需要设置 ShowValueLabels = true 才会显示
barPlot.ShowValueLabels = true;

barPlot.SetMarginPercent(bottom: 0, top: 0.15);
barPlot.RefreshPlot();

带值标签的柱状图

csharp 复制代码
double[] values = { 5, 10, 7, 13 };
var series = barPlot.AddBars(values);

// 为每个柱子设置值标签
foreach (var item in series.Items)
{
    item.ValueLabel = item.Value.ToString();
}

// 显示值标签
barPlot.ShowValueLabels = true;

// 设置样式
series.ValueLabelStyle.Bold = true;
series.ValueLabelStyle.FontSize = 14;

// 设置边距:底部为0,顶部预留20%空间给标签
barPlot.SetMarginPercent(bottom: 0, top: 0.2);

barPlot.RefreshPlot();

对比柱状图

csharp 复制代码
// 第一组数据
double[] values1 = { 5, 10, 7, 13 };
var series1 = barPlot.AddBars(values1);
series1.LegendText = "Alpha";
series1.Color = Color.FromArgb(24, 144, 255);  // 蓝色

// 第二组数据
double[] values2 = { 7, 12, 9, 15 };
var series2 = barPlot.AddBars(values2);
series2.LegendText = "Beta";
series2.Color = Color.FromArgb(103, 194, 58);  // 绿色

// 显示图例
barPlot.ShowLegend = true;
barPlot.LegendPosition = LegendPosition.Right;  // 图例显示在数据区右侧

// 设置底部边距
barPlot.MarginBottomPercent = 0;

barPlot.RefreshPlot();

带标题的柱状图

csharp 复制代码
barPlot.Title = "2024年销售数据";
barPlot.TitlePosition = TitlePosition.Center;  // 标题居中
barPlot.TitleBold = true;                      // 标题加粗
barPlot.TitleFontSize = 16;                    // 标题字号
barPlot.TitleColor = Color.DodgerBlue;         // 标题颜色
barPlot.TitleMargin = 15;                      // 标题与图表间距

barPlot.RefreshPlot();

坐标轴箭头

csharp 复制代码
barPlot.ShowAxisArrows = true;   // 显示坐标轴箭头
barPlot.ArrowSize = 10;          // 箭头大小

// 为Y轴标签预留空间,防止箭头与网格线太近
barPlot.SetMarginPercent(bottom: 0, top: 0.15);

barPlot.RefreshPlot();

网格线样式

csharp 复制代码
// 显示网格线
barPlot.ShowGrid = true;
barPlot.ShowHorizontalGrid = true;   // 水平网格线(默认)
barPlot.ShowVerticalGrid = true;     // 垂直网格线

// 网格线样式(细线更丝滑)
barPlot.GridLineWidth = 0.5f;                    // 线宽0.5像素
barPlot.GridLineStyle = DashStyle.Solid;         // 实线(默认)
barPlot.GridColor = Color.FromArgb(220, 220, 220); // 淡灰色

barPlot.RefreshPlot();

背景设置

csharp 复制代码
// 背景色
barPlot.BackColor = Color.LightBlue;

// 或背景图
barPlot.BackgroundImage = Image.FromFile("background.png");
barPlot.BackgroundImageLayout = ImageLayout.Zoom;  // None/Tile/Center/Stretch/Zoom

X轴标签旋转

csharp 复制代码
// X轴标签旋转45度,避免重叠
barPlot.XAxisLabelAngle = 45;

// 调整标签与轴线的距离
barPlot.XAxisLabelOffset = 10;

// 显示X轴刻度线
barPlot.ShowXAxisTicks = true;
barPlot.XAxisTickLength = 6;

barPlot.RefreshPlot();

图例样式

csharp 复制代码
barPlot.ShowLegend = true;
barPlot.LegendPosition = LegendPosition.TopRight;  // 图例位置

// 图例背景
barPlot.LegendShowBackground = true;
barPlot.LegendBackColor = Color.White;

// 图例边框
barPlot.LegendShowBorder = true;
barPlot.LegendBorderColor = Color.Gray;
barPlot.LegendBorderWidth = 1;

barPlot.RefreshPlot();

属性说明

数据属性

属性名 类型 默认值 说明
Series List - 数据系列集合
ColorType ColorType Primary 色彩类型(Primary/Success/Warning/Error/Info)

显示属性

属性名 类型 默认值 说明
ShowGrid bool true 是否显示网格线
ShowHorizontalGrid bool true 是否显示水平网格线
ShowVerticalGrid bool false 是否显示垂直网格线
ShowLegend bool false 是否显示图例
ShowAxis bool true 是否显示坐标轴
ShowValueLabels bool false 是否显示值标签
ShowXAxisTicks bool true 是否显示X轴刻度线
ShowAxisArrows bool false 是否显示坐标轴箭头

布局属性

属性名 类型 默认值 说明
BarSpacing double 0.1 同一分类内柱子之间的间距比例(0-1)
CategorySpacing double 0.2 不同分类之间的间距比例(0-1)
XAxisLabelAngle float 0 X轴标签旋转角度(度)
XAxisLabelOffset float 6 X轴标签与轴线的距离(像素)
XAxisTickLength float 5 X轴刻度线长度(像素)

边距属性

属性名 类型 默认值 说明
MarginLeft float 50 左侧边距(像素)
MarginRight float 20 右侧边距(像素)
MarginTop float 20 顶部边距(像素)
MarginBottom float 40 底部边距(像素)
MarginBottomPercent double 0 底部边距百分比(0-1)
MarginTopPercent double 0 顶部边距百分比(0-1)

网格线属性

属性名 类型 默认值 说明
GridLineWidth float 0.5 网格线宽度(像素,细线更丝滑)
GridLineStyle DashStyle Solid 网格线样式(Solid/Dash/Dot等)
GridColor Color #E6E6E6 网格线颜色

标题属性

属性名 类型 默认值 说明
Title string "" 标题文本
TitlePosition TitlePosition Center 标题位置(Left/Center/Right)
TitleBold bool true 标题是否加粗
TitleFontSize float 14 标题字体大小
TitleColor Color Empty 标题颜色(空则使用主题色)
TitleMargin float 10 标题与图表区域的间距

图例属性

属性名 类型 默认值 说明
LegendPosition LegendPosition TopRight 图例位置
LegendShowBackground bool true 是否显示图例背景
LegendShowBorder bool true 是否显示图例边框
LegendBackColor Color White 图例背景色
LegendBorderColor Color Empty 图例边框色(空则使用轴线颜色)
LegendBorderWidth int 1 图例边框宽度
LegendWidth int 100 图例宽度(用于Right/Left位置)

箭头属性

属性名 类型 默认值 说明
ShowAxisArrows bool false 是否显示坐标轴箭头
ArrowSize float 8 箭头大小(像素)

主题属性

属性名 类型 默认值 说明
FollowGlobalTheme bool true 是否跟随全局主题变化

动画属性

属性名 类型 默认值 说明
EnableAnimation bool true 是否启用柱状图生长动画
AnimationDuration int 800 动画时长(毫秒,范围100-5000)

BarSeries 数据系列

属性

属性名 类型 默认值 说明
Name string "" 系列名称
LegendText string "" 图例文本
Items List - 数据项集合
Color Color Empty 系列颜色(为空则使用主题色)
BorderColor Color Empty 边框颜色
BorderWidth int 1 边框宽度
BarWidth double 0.7 柱子宽度比例(0-1)
ValueLabelStyle ValueLabelStyle - 值标签样式

方法

方法名 说明
Add(double value, string label) 添加数据项
FromValues(double[] values) 从数组创建系列

BarItem 数据项

属性名 类型 默认值 说明
Value double 0 数据值
Label string "" X轴标签
ValueLabel string "" 值标签(显示在柱子上方)
Color Color Empty 自定义颜色
LegendText string "" 图例文本

ValueLabelStyle 值标签样式

属性名 类型 默认值 说明
Visible bool false 是否显示
FontSize float 10 字体大小
Bold bool false 是否粗体
ForeColor Color Empty 字体颜色
Offset int 4 距离柱子顶部的偏移

动画效果

BarPlotEx 支持柔和的生长动画效果,让柱状图从底部向上生长显示。

启用/禁用动画

csharp 复制代码
// 启用动画(默认)
barPlot.EnableAnimation = true;

// 禁用动画
barPlot.EnableAnimation = false;

调整动画时长

csharp 复制代码
// 设置动画时长为 1.2 秒(范围 100-5000 毫秒)
barPlot.AnimationDuration = 1200;

动画效果说明

  • 生长动画:柱子从底部向上生长,使用 EaseOutCubic 缓动函数,开始快结束慢,效果柔和自然
  • 值标签淡入:值标签在动画进度达到 70% 时开始淡入显示,带有透明度渐变效果
  • 自动触发 :调用 AddBars() 添加数据时自动触发动画
  • RefreshPlot 重播 :调用 RefreshPlot() 刷新图表时会重新播放动画(需启用动画)
  • 手动重播 :调用 ReplayAnimation() 可随时重新播放动画
  • 设计模式:在设计模式下自动禁用动画,避免设计器闪烁

重新播放动画

csharp 复制代码
// 方式1:调用 RefreshPlot(会重新计算范围并重播动画)
barPlot.RefreshPlot();

// 方式2:只重新播放动画(不重新计算数据范围)
barPlot.ReplayAnimation();

公共方法

方法名 说明
AddBars(double[] values, string? name) 从数值数组添加柱状图(自动播放动画)
AddBars(double[] values, string[] labels, string? name) 从数值数组和X轴标签数组添加柱状图(自动播放动画)
AddBars(double[] values, string[] labels, string? name, bool showValueLabels) 从数值数组和X轴标签数组添加柱状图,自动显示数值作为值标签(自动播放动画)
AddBars(double[] values, string[] labels, string[] valueLabels, string? name) 从数值数组、X轴标签数组和值标签数组添加柱状图(自动播放动画)
AddSeries(string name) 添加空数据系列(自动播放动画)
Clear() 清空所有数据
RefreshPlot() 刷新图表(如果启用了动画会自动重新播放)
ReplayAnimation() 重新播放柱状图生长动画
SetMargins(left, right, top, bottom) 设置像素边距
SetMarginPercent(bottom, top) 设置百分比边距

枚举类型

LegendPosition(图例位置)

说明
TopLeft 左上角(控件边缘)
TopRight 右上角(控件边缘)
BottomLeft 左下角(控件边缘)
BottomRight 右下角(控件边缘)
Right 数据区域右侧
Left 数据区域左侧

TitlePosition(标题位置)

说明
Left 左对齐
Center 居中(默认)
Right 右对齐

ColorType(色彩类型)

说明
Primary 蓝色
Success 绿色
Warning 橙色
Error 红色
Info 深蓝色

主题适配

控件自动支持亮暗主题切换:

csharp 复制代码
// 亮色主题(默认)
- 背景色: 白色
- 前景色: #333333
- 网格线: #E6E6E6
- 坐标轴: #C8C8C8

// 暗色主题
- 背景色: #1E1E1E
- 前景色: #FFFFFF
- 网格线: #3C3C3C
- 坐标轴: #646464

色彩模式

ColorType 亮色模式 暗色模式
Primary 蓝色 蓝色
Success 绿色 绿色
Warning 橙色 橙色
Error 红色 红色
Info 深蓝 深蓝

完整实例

示例1:基础柱状图

csharp 复制代码
public void Demo1_BasicBarChart()
{
    var barPlot = new BarPlotEx
    {
        Dock = DockStyle.Fill,
        Title = "基础柱状图示例",
        TitlePosition = TitlePosition.Center,
        TitleFontSize = 16,
        ColorType = ColorType.Primary
    };

    // 添加数据
    double[] values = { 25, 40, 35, 55 };
    var series = barPlot.AddBars(values, "销售额");

    // 设置X轴标签
    series.Items[0].Label = "Q1";
    series.Items[1].Label = "Q2";
    series.Items[2].Label = "Q3";
    series.Items[3].Label = "Q4";

    // 设置边距使柱子贴底
    barPlot.SetMarginPercent(bottom: 0, top: 0.1);
    
    barPlot.RefreshPlot();
    this.Controls.Add(barPlot);
}

示例2:多系列对比

csharp 复制代码
public void Demo2_MultiSeries()
{
    var barPlot = new BarPlotEx
    {
        Dock = DockStyle.Fill,
        Title = "季度销售对比",
        ShowLegend = true,
        LegendPosition = LegendPosition.Right,
        ShowValueLabels = true
    };

    // 2023年数据
    var series2023 = barPlot.AddBars(new double[] { 100, 120, 140, 160 }, "2023年");
    series2023.Color = Color.FromArgb(24, 144, 255);

    // 2024年数据
    var series2024 = barPlot.AddBars(new double[] { 110, 135, 155, 180 }, "2024年");
    series2024.Color = Color.FromArgb(103, 194, 58);

    // 设置标签
    string[] labels = { "Q1", "Q2", "Q3", "Q4" };
    for (int i = 0; i < 4; i++)
    {
        series2023.Items[i].Label = labels[i];
        series2024.Items[i].ValueLabel = series2024.Items[i].Value.ToString();
    }

    // 图例样式
    barPlot.LegendShowBackground = true;
    barPlot.LegendBackColor = Color.White;
    barPlot.LegendShowBorder = true;

    // 网格线
    barPlot.ShowHorizontalGrid = true;
    barPlot.ShowVerticalGrid = true;
    barPlot.GridLineWidth = 0.5f;

    barPlot.SetMarginPercent(bottom: 0, top: 0.15);
    barPlot.RefreshPlot();
    this.Controls.Add(barPlot);
}

示例3:带坐标轴箭头和X轴旋转

csharp 复制代码
public void Demo3_ArrowsAndRotatedLabels()
{
    var barPlot = new BarPlotEx
    {
        Dock = DockStyle.Fill,
        Title = "产品销售数据",
        TitleBold = true,
        TitleColor = Color.DodgerBlue
    };

    // 添加数据
    double[] values = { 120, 200, 150, 80, 250 };
    var series = barPlot.AddBars(values, "销量");

    // 长标签需要旋转
    string[] products = { "笔记本电脑", "智能手机", "平板电脑", "智能手表", "无线耳机" };
    for (int i = 0; i < products.Length; i++)
    {
        series.Items[i].Label = products[i];
    }

    // X轴标签旋转45度,避免重叠
    barPlot.XAxisLabelAngle = 45;
    barPlot.XAxisLabelOffset = 10;
    barPlot.ShowXAxisTicks = true;
    barPlot.XAxisTickLength = 6;

    // 坐标轴箭头
    barPlot.ShowAxisArrows = true;
    barPlot.ArrowSize = 10;

    // 网格线样式(细线更丝滑)
    barPlot.GridLineWidth = 0.5f;
    barPlot.GridColor = Color.FromArgb(220, 220, 220);

    // 预留空间给箭头和标签
    barPlot.SetMarginPercent(bottom: 0.05, top: 0.15);

    barPlot.RefreshPlot();
    this.Controls.Add(barPlot);
}

示例4:暗色主题背景图

csharp 复制代码
public void Demo4_DarkThemeWithBackground()
{
    var barPlot = new BarPlotEx
    {
        Dock = DockStyle.Fill,
        Title = "暗色主题示例",
        TitleColor = Color.White,
        ColorType = ColorType.Warning
    };

    // 设置暗色背景
    barPlot.BackColor = Color.FromArgb(30, 30, 30);

    // 或设置背景图
    // barPlot.BackgroundImage = Image.FromFile("dark-bg.png");
    // barPlot.BackgroundImageLayout = ImageLayout.Stretch;

    // 添加数据
    double[] values = { 65, 78, 90, 81, 56 };
    var series = barPlot.AddBars(values);

    string[] months = { "一月", "二月", "三月", "四月", "五月" };
    for (int i = 0; i < months.Length; i++)
    {
        series.Items[i].Label = months[i];
        series.Items[i].ValueLabel = values[i].ToString();
    }

    barPlot.ShowValueLabels = true;
    barPlot.SetMarginPercent(bottom: 0, top: 0.15);
    barPlot.RefreshPlot();
    this.Controls.Add(barPlot);
}

注意事项

  1. 边距设置MarginBottomPercent = 0 可使柱子贴底显示,参考 ScottPlot 的 Axes.Margins(bottom: 0)
  2. 值标签空间 :显示值标签时,建议设置 MarginTopPercent = 0.15-0.2 预留顶部空间
  3. 数据范围 :控件会自动计算数据范围,最大值会根据 MarginTopPercent 自动调整
  4. 多系列宽度:多系列数据时,柱子会自动平分分类宽度
  5. 主题切换 :设置 FollowGlobalTheme = false 可禁用自动主题切换
  6. Y轴箭头:箭头显示在最顶部,自动预留空间防止与网格线重叠
  7. 图例位置:所有图例位置都在数据区域外部,不会遮挡数据
  8. X轴旋转标签 :旋转后的标签从轴线下方开始,使用 XAxisLabelOffset 调整距离
  9. 动画效果:添加数据后自动播放生长动画,设计模式下自动禁用

版本历史

版本 日期 更新内容
1.0 2025-04-20 初始版本
1.1 2025-04-23 添加 AddBars 数组重载方法(支持 X轴标签、值标签数组)
1.2 2025-04-23 添加柱状图生长动画效果

三、后记

陆续补充完善中,如有需求,请留言

相关推荐
for_ever_love__3 小时前
UI学习:多界面传值的正向传值(属性传值)和反向传值(代理传值)
学习·ui·ios·objective-c
Python私教5 小时前
FuturesDesk:配置驱动 UI 的 Electron 金融桌面应用模板
ui·金融·electron
椰羊~王小美5 小时前
LVGL 界面UI库
ui
久爱物联网8 小时前
【WinForm UI控件系列】Breadcrumb 面包屑控件,支持三种样式
ui·breadcrumb·面包屑控件·winformui·csharpui控件·桌面ui控件
久爱物联网9 小时前
【WinForm UI控件系列】PieChart饼状图控件
ui·winformui控件·c#控件ui·桌面应用ui控件·gdi绘制控件
久爱物联网9 小时前
【WinForm UI控件系列】Blower 鼓风机控件
ui·ui控件·桌面应用控件·鼓风机控件·winfrom控件
久爱物联网10 小时前
【WinForm UI控件系列】Battery 电池电量控件
ui·winformui控件·桌面应用控件·c#控件ui·ui控件gdi
ZC跨境爬虫11 小时前
UI前端美化技能提升日志day5:从布局优化到CSS继承原理深度解析
前端·css·ui·html·状态模式
久爱物联网11 小时前
【WinForm UI控件系列】AlarmLight 报警灯\声光报警灯控件
ui·winformui控件·桌面应用控件·c# ui控件·gdi控件 net控件