最近因为公司项目需要用到WinForm的DecExpress控件,在这里把一些使用方法总结一下。
DevExpress中有一个专门用来绘制图表的插件ChartControl,可以绘制折线图、饼状图、柱状图等图表。
一.绘制图表基本步骤
(一):准备数据并绑定
这里从数据库中取得数据,可以根据自己的需要修改。
1 DataTable dtData = BF<bll_ep_collection_data>.Instance.GetDataTable(sqlwhere, "data_time", parameters);
2 //建立新的datatable,用来存储XY坐标
3 DataTable dtXY = new DataTable();
4 //横坐标的值
5 dtXY.Columns.Add(new DataColumn("类型"));
6 var list = new List<object>();
7 //纵坐标的值
8 list.Add("数值");
9 //这里是控制x轴显示数据的数量,ArgumentScaleType类型设置为ScaleType.Qualitative时他不会自动控制x轴的数量
10 //如果得到数据小于X_COUNT,则x轴显示全部得到的数据
11 if (X_COUNT < dtData.Rows.Count)
12 {
13 for (int i = 0; i < X_COUNT; i++)
14 {
15 int index = (dtData.Rows.Count / X_COUNT) * i;
16 DataRow item = dtData.Rows[index];
17 dtXY.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(decimal)));
18 list.Add(item["value"]);
19 }
20 }
21 //如果得到数据大于X_COUNT,则x轴X_COUNT条数据
22 else
23 {
24 for (int i = 0; i < dtData.Rows.Count; i++)
25 {
26 DataRow item = dtData.Rows[i];
27 dtXY.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(decimal)));
28 list.Add(item["value"]);
29 }
30 }
31 var array = list.ToArray();
32 dtXY.Rows.Add(array);
33 this.chartControl1.DataSource = dtXY;
一个更直白的例子:
1 DataTable dt = new DataTable();
2 dt.Columns.Add(new DataColumn("类型"));
3 dt.Columns.Add(new DataColumn("2005-1月", typeof(decimal)));
4 dt.Columns.Add(new DataColumn("2005-2月", typeof(decimal)));
5 dt.Columns.Add(new DataColumn("2005-3月", typeof(decimal)));
6 dt.Columns.Add(new DataColumn("2005-4月", typeof(decimal)));
7 dt.Columns.Add(new DataColumn("2005-5月", typeof(decimal)));
8 dt.Columns.Add(new DataColumn("2005-6月", typeof(decimal)));
9
10 dt.Rows.Add(new object[] { "员工人数", 437, 437, 414, 397, 387, 378 });
11 dt.Rows.Add(new object[] { "人均月薪", 3964, 3961, 3979, 3974, 3967, 3972 });
12 dt.Rows.Add(new object[] { "成本TEU", 3104, 1339, 3595.8, 3154.5, 2499.8, 3026 });
13 dt.Rows.Add(new object[] { "人均生产率", 7.1, 3.06, 8.69, 7.95, 6.46, 8.01 });
14 dt.Rows.Add(new object[] { "占2005年3月人数比例", 1.06, 1.06, 1, 0.96, 0.93, 0.91 });
(二):根据数据创建图形展现
CreateSeries用于创建一个典型的图形,这里展示创建一条曲线。
1 /// <summary>
2 /// 根据数据创建一个图形展现
3 /// </summary>
4 /// <param name="caption">图形标题</param>
5 /// <param name="viewType">图形类型</param>
6 /// <param name="dt">数据DataTable</param>
7 /// <param name="rowIndex">图形数据的行序号</param>
8 /// <returns></returns>
9 private Series CreateSeries(string caption, ViewType viewType, DataTable dt, int rowIndex)
10 {
11 Series series = new Series(caption, viewType);
12 for (int i = 1; i < dt.Columns.Count; i++)
13 {
14 string argument = dt.Columns[i].ColumnName;//参数名称
15 decimal value = (decimal)dt.Rows[rowIndex][i];//参数值
16 series.Points.Add(new SeriesPoint(argument, value));
17 }
18 //必须设置ArgumentScaleType的类型,否则显示会转换为日期格式,导致不是希望的格式显示
19 //也就是说,显示字符串的参数,必须设置类型为ScaleType.Qualitative
20 series.ArgumentScaleType = ScaleType.Qualitative;
21 //series.ArgumentScaleType = ScaleType.DateTime;
22 series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.False;//显示标注标签
23 return series;
24 }
(三):根据图形对象创建一个图表并绑定到CharControl中
1 /// <summary>
2 /// 根据图形对象创建一个图表
3 /// </summary>
4 /// <param name="chartControl">图表绑定控件</param>
5 /// <param name="list">图表中的图形展现</param>
6 /// <returns></returns>
7 private void CreateChart(ChartControl chartControl, List<Series> list)
8 {
9 chartControl.Series.AddRange(list.ToArray());
10 chartControl.Legend.Visible = false;
11 chartControl.SeriesTemplate.LabelsVisibility = DefaultBoolean.False;
12 //XYDiagram diagram = (XYDiagram)chartControl1.Diagram;
13 //diagram.AxisX.DateTimeMeasureUnit = DateTimeMeasurementUnit.Second;
14 //diagram.AxisX.DateTimeOptions.Format = DateTimeFormat.Custom;
15 //diagram.AxisX.DateTimeOptions.FormatString = "yyyy-MM-dd HH:mm:ss";
16 }
(四):调用函数绘制图表
1 //清空ChartControl控件
2 chartControl1.Series.Clear();
3 //创建图形对象的列表
4 List<Series> list = new List<Series>();
5 foreach (DataRowView item in listBox.Items)
6 {
7 string str = item["key"].ToString();
8 //通过LoadData返回一个DataTable
9 DataTable dtXY = LoadData(str);
10 //创建一个图形对象
11 Series series = CreateSeries(caption, type, dtXY, 0);;
12 list.Add(series);
13 }
14 //根据图形对象列表创建一个图表
15 CreateChart(chartControl1, list);
小结:在绘制折线图的时候我遇到的一个很大的问题就是没办法控制数据的显示数量,因为数据库中存储的数据量过大,在一定时间段内的数据都能达到上千条,所以不可能一次性全部显示。我想到的解决办法是固定显示多少条数据,比如说20条,然后根据数据量每隔一段距离取一条数据显示。
二.柱状图
绘制柱状图其实和绘制折线图没有什么区别,就是将new Series时的图形类型改为ViewType.Bar即可,这里我想总结一下一个困扰我很久的问题,如何绘制上图所示的一个横坐标对应两个或者多个柱子。
(一): 准备数据
1 DataTable dtData = SqlHelper.GetDataSet(sql, parameters).Tables[0];
2 //建立新的datatable,用来存储XY坐标
3 DataTable dtXY_max = new DataTable();
4 DataTable dtXY_min = new DataTable();
5 dtXY_max.Columns.Add(new DataColumn("类型"));
6 dtXY_min.Columns.Add(new DataColumn("类型"));
7 var list_max = new List<object>();
8 list_max.Add("数值");
9 var list_min = new List<object>();
10 list_min.Add("数值");
11 for (int i = 0; i < dtData.Rows.Count; i++)
12 {
13 DataRow item = dtData.Rows[i];
14 string value = item["max"].ToString() + "|" + item["min"].ToString();
15 //dtXY.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(string)));
16 //list.Add(value);
17 dtXY_max.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(decimal)));
18 list_max.Add(item["max"]);
19 dtXY_min.Columns.Add(new DataColumn(item["data_time"].ToString(), typeof(decimal)));
20 list_min.Add(item["min"]);
21 }
22 var array_max = list_max.ToArray();
23 dtXY_max.Rows.Add(array_max);
24 var array_min = list_min.ToArray();
25 dtXY_min.Rows.Add(array_min);
(二):创建图形展现对象方法
1 /// <summary>
2 /// 根据数据创建一个图形展现
3 /// </summary>
4 /// <param name="caption">图形标题</param>
5 /// <param name="viewType">图形类型</param>
6 /// <param name="dt">数据DataTable</param>
7 /// <param name="rowIndex">图形数据的行序号</param>
8 /// <returns></returns>
9 private Series CreateSeries(string caption, ViewType viewType, DataTable dt, int rowIndex)
10 {
11 Series series = new Series(caption, viewType);
12 for (int i = 1; i < dt.Columns.Count; i++)
13 {
14 string argument = dt.Columns[i].ColumnName;//参数名称
15 decimal value = (decimal) dt.Rows[rowIndex][i];
16 series.Points.Add(new SeriesPoint(argument, value));
17 }
18 //柱状图柱子的宽度设置
19 //BarSeriesView bsv = (BarSeriesView)series.View;
20 //bsv.BarWidth = 0.1;
21 //必须设置ArgumentScaleType的类型,否则显示会转换为日期格式,导致不是希望的格式显示
22 //也就是说,显示字符串的参数,必须设置类型为ScaleType.Qualitative
23 series.ArgumentScaleType = ScaleType.Qualitative;
24 //series.ArgumentScaleType = ScaleType.DateTime;
25 series.LabelsVisibility = DevExpress.Utils.DefaultBoolean.True;//显示标注标签
26 return series;
27 }
(三):根据图形对象创建图表
1 /// <summary>
2 /// 根据图形对象创建一个图表
3 /// </summary>
4 /// <param name="chartControl">图标绑定控件</param>
5 /// <param name="list">图表中的图形展现</param>
6 /// <returns></returns>
7 private void CreateChart(ChartControl chartControl, List<Series> series)
8 {
9 chartControl.Series.AddRange(series.ToArray());
10 //chartControl.Series.Add(series);
11 chartControl.Legend.Visible = true;
12 chartControl.SeriesTemplate.LabelsVisibility = DefaultBoolean.True;
13 XYDiagram xydiagram = (XYDiagram)chartControl.Diagram;
14 xydiagram.AxisX.MinorCount = 10;
15 }
三.饼状图
(一):准备数据
1 private DataTable CreateChartData()
2 {
3 DataTable dtData = SqlHelper.GetDataSet(sql, parameters).Tables[0];
4 DataTable table = new DataTable("Table1");
5 table.Columns.Add("Name", typeof(String));
6 table.Columns.Add("Value", typeof(Double));
7 foreach (DataRow item in dtData.Rows)
8 {
9 var array = new object[] { item["value_num"], item["count"] };
10 table.Rows.Add(array);
11 }
12 return table;
13 }
(二):创建一个饼状图
1 /// <summary>
2 /// 根据数据创建一个饼状图
3 /// </summary>
4 /// <returns></returns>
5 private void BuilderDevChart()
6 {
7 Series _pieSeries = new Series("测试", ViewType.Pie);
8 _pieSeries.ValueDataMembers[0] = "Value";
9 _pieSeries.ArgumentDataMember = "Name";
10 _pieSeries.DataSource = CreateChartData();
11 chartControl1.Series.Add(_pieSeries);
12 _pieSeries.SetPiePercentage();
13 _pieSeries.LegendPointOptions.PointView = PointView.ArgumentAndValues;
14 }
(三):设置饼状图显示方式(数值/百分比)
1 public static class ExtensionClass
2 {
3 /// <summary>
4 /// 设置饼状Series显示方式(值/百分比)
5 /// </summary>
6 /// <param name="series">Series</param>
7 public static void SetPiePercentage(this Series series)
8 {
9 if (series.View is PieSeriesView)
10 {
11 //设置为值
12 //((PiePointOptions)series.PointOptions).PercentOptions.ValueAsPercent = false;
13 //((PiePointOptions)series.PointOptions).ValueNumericOptions.Format = NumericFormat.Number;
14 //((PiePointOptions)series.PointOptions).ValueNumericOptions.Precision = 0;
15 //设置为百分比
16 ((PiePointOptions)series.PointOptions).PercentOptions.ValueAsPercent = true;
17 ((PiePointOptions)series.PointOptions).ValueNumericOptions.Format = NumericFormat.Percent;
18 ((PiePointOptions)series.PointOptions).ValueNumericOptions.Precision = 0;
19 }
20 }
21 }