WinForm中使用DevExpress ChartControl绘制折线图、柱状图与饼状图

Finn
Finn
发布时间:2026-10-15 | 4人浏览过
原创

在WinForm开发中,使用DevExpress的ChartControl控件可以高效实现复杂的数据可视化需求。本文将展示如何通过预处理DataTable数据,动态构建Series对象并绑定至ChartControl,涵盖折线图、分组柱状图及饼状图的绘制逻辑,重点解决大数据量下的X轴显示优化及标签格式化问题。

绘制图表基本步骤

使用ChartControl的核心流程包括数据清洗、Series创建以及图表绑定。首先需从数据库或内存中提取数据,整理为符合图表要求的结构(通常为第一列为维度/X轴,后续列为数值/Y轴),然后通过编程方式生成图形实例。

第1步:准备并处理数据

ChartControl通常依赖DataTable作为数据源。若原始数据量过大(如上千条记录),直接绑定会导致X轴拥挤无法阅读。此时需按策略采样数据,例如固定显示X_COUNT条数据,根据总量间隔取值。

// 假设已通过sql获取基础数据表dtData
DataTable dtData = BF.Instance.GetDataTable(sqlwhere, "data_time", parameters);

// 建立存储XY坐标的新表
DataTable dtXY = new DataTable();
dtXY.Columns.Add(new DataColumn("类型"));
var list = new List();
list.Add("数值");

// 控制X轴显示数据的数量采样逻辑
if (X_COUNT < dtData.Rows.Count)
{
    for (int i = 0; i < X_COUNT; i++)
    {
        // 间隔采样
        int index = (dtData.Rows.Count / X_COUNT) * i;
        DataRow item = dtData.Rows[index];
        dtXY.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(decimal)));
        list.Add(item["value"]);
    }
}
else
{
    // 数据量小于阈值时全部显示
    for (int i = 0; i < dtData.Rows.Count; i++)
    {
        DataRow item = dtData.Rows[i];
        dtXY.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(decimal)));
        list.Add(item["value"]);
    }
}

var array = list.ToArray();
dtXY.Rows.Add(array);
// 将处理后的DataTable绑定到控件
this.chartControl1.DataSource = dtXY;

直观的数据结构示例:

DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("类型"));
// 动态添加月份列作为X轴维度
for(int i=1; i<=6; i++)
    dt.Columns.Add(new DataColumn($"2005-{i}月", typeof(decimal)));

// 填充各行数据
// Row 1: 员工人数, 437, 437, ...
// Row 2: 人均月薪, 3964, 3961, ...

第2步:根据数据创建图形展现 (Series)

遍历DataTable的每一行数据,将其转换为Series对象。关键注意点:当X轴参数为字符串或非标准日期格式时,必须设置ArgumentScaleType为Qualitative,否则DevExpress可能会尝试将其解析为日期,导致显示错误或格式混乱。

/// 
/// 根据数据创建一个图形展现
/// 
private Series CreateSeries(string caption, ViewType viewType, DataTable dt, int rowIndex)
{
    Series series = new Series(caption, viewType);
    
    // 遍历除第一列(类别列)外的所有列
    for (int i = 1; i < dt.Columns.Count; i++)
    {
        string argument = dt.Columns[i].ColumnName; // X轴标签
        decimal value = (decimal)dt.Rows[rowIndex][i]; // Y轴数值
        series.Points.Add(new SeriesPoint(argument, value));
    }

    // 强制设定X轴类型为定性分类,避免日期自动转换
    series.ArgumentScaleType = ScaleType.Qualitative;
    
    // 隐藏Series默认标签,统一由图表管理或自定义
    series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;
    return series;
}

第3步:组合图形并绑定到ChartControl

将生成的多个Series添加到ChartControl中,并配置图表属性(如图例可见性、模板标签等)。

private void CreateChart(ChartControl chartControl, List list)
{
    chartControl.Series.AddRange(list.ToArray());
    chartControl.Legend.Visible = false; // 按需开启图例
    chartControl.SeriesTemplate.LabelsVisibility = DefaultBoolean.False;
}

// 调用示例
chartControl1.Series.Clear();
List list = new List();
foreach (DataRowView item in listBox.Items)
{
    string str = item["key"].ToString();
    DataTable dtXY = LoadData(str); // 获取对应数据的DataTable
    Series series = CreateSeries(caption, type, dtXY, 0);
    list.Add(series);
}
CreateChart(chartControl1, list);

柱状图绘制与多系列分组

柱状图只需将CreateSeries中的viewType改为ViewType.Bar。若要实现“一个横坐标对应多个柱子”的效果(即分组柱状图),需分别为每个系列准备独立的DataTable,分别传入CreateSeries方法,最后合并添加至图表中。

第1步:拆分数据以支持分组

若有最大值和最小值两组数据,应创建两个DataTable,分别装载对应的列数据。

DataTable dtData = SqlHelper.GetDataSet(sql, parameters).Tables[0];
DataTable dtXY_max = new DataTable();
DataTable dtXY_min = new DataTable();
dtXY_max.Columns.Add(new DataColumn("类型"));
dtXY_min.Columns.Add(new DataColumn("类型"));

var list_max = new List { "数值" };
var list_min = new List { "数值" };

for (int i = 0; i < dtData.Rows.Count; i++)
{
    DataRow item = dtData.Rows[i];
    // 时间作为列名
    string timeColName = item["data_time"].ToString();
    
    dtXY_max.Columns.Add(new DataColumn(timeColName, typeof(decimal)));
    list_max.Add(item["max"]);
    
    dtXY_min.Columns.Add(new DataColumn(timeColName, typeof(decimal)));
    list_min.Add(item["min"]);
}

dtXY_max.Rows.Add(list_max.ToArray());
dtXY_min.Rows.Add(list_min.ToArray());

第2步:创建并配置分组柱状图

注意:在分组显示时,通常需要开启图例并可能需要调整X轴的刻度显示。

private void CreateChart(ChartControl chartControl, List series)
{
    chartControl.Series.AddRange(series.ToArray());
    chartControl.Legend.Visible = true; // 分组图建议开启图例
    chartControl.SeriesTemplate.LabelsVisibility = DefaultBoolean.True;
    
    XYDiagram xydiagram = (XYDiagram)chartControl.Diagram;
    xydiagram.AxisX.MinorCount = 10; // 辅助刻度调整
}

// 使用时分别调用CreateSeries创建Max和Min两条曲线
List groupList = new List();
groupList.Add(CreateSeries("最大值", ViewType.Bar, dtXY_max, 0));
groupList.Add(CreateSeries("最小值", ViewType.Bar, dtXY_min, 0));
CreateChart(chartControl1, groupList);

饼状图绘制与百分比设置

饼状图的DataStructure与前述两种图表不同,它不需要宽格式的Table(即不需要列名为X轴),而是需要长格式的两列表:Name(分类名称)和Value(数值)。同时需要使用扩展方法灵活控制显示内容为百分比还是具体数值。

第1步:构建饼图专用DataTable

private DataTable CreateChartData()
{
    DataTable dtData = SqlHelper.GetDataSet(sql, parameters).Tables[0];
    DataTable table = new DataTable("Table1");
    table.Columns.Add("Name", typeof(String));   // 分类项
    table.Columns.Add("Value", typeof(Double));  // 数值项
    
    foreach (DataRow item in dtData.Rows)
    {
        var array = new object[] { item["value_num"], item["count"] };
        table.Rows.Add(array);
    }
    return table;
}

第2步:初始化饼图Series

利用ValueDataMember和ArgumentDataMember指定数据源列。

private void BuilderDevChart()
{
    Series _pieSeries = new Series("测试数据", ViewType.Pie);
    _pieSeries.ValueDataMembers[0] = "Value";
    _pieSeries.ArgumentDataMember = "Name";
    _pieSeries.DataSource = CreateChartData();
    
    chartControl1.Series.Add(_pieSeries);
    
    // 设置为百分比显示
    _pieSeries.SetPiePercentage();
    
    // 设置提示显示格式:名称+数值
    _pieSeries.LegendPointOptions.PointView = PointView.ArgumentAndValues;
}

第3步:配置显示样式(数值vs百分比)

可通过扩展类快速切换饼图标签格式。

public static class ExtensionClass
{
    public static void SetPiePercentage(this Series series)
    {
        if (series.View is PieSeriesView)
        {
            PiePointOptions pointOpt = (PiePointOptions)series.PointOptions;
            
            // 切换为百分比模式
            pointOpt.PercentOptions.ValueAsPercent = true;
            pointOpt.ValueNumericOptions.Format = NumericFormat.Percent;
            pointOpt.ValueNumericOptions.Precision = 0;
            
            /* 若需切换回数值显示,可取消注释以下代码:
            pointOpt.PercentOptions.ValueAsPercent = false;
            pointOpt.ValueNumericOptions.Format = NumericFormat.Number;
            */
        }
    }
}
以上就是WinForm使用DevExpress ChartControl绘制常用图表的详细内容,更多关于C# WinForm图表开发技巧的资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表