using DevExpress.Charts.Native;
using DevExpress.Utils.Extensions;
using DevExpress.XtraCharts;
using DevExpress.XtraEditors;
using DevExpress.XtraLayout;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExtensionsDev
{
public static class ChartExtension
{
private enum EnumTimeType
{
Year,
Month,
Day,
Hour,
Minute,
Second,
Millisecond
}
private class ChartOptions
{
public int XLableCount { get; set; } = 5;
public EnumTimeType TimeType { get; set; } = EnumTimeType.Second;
public bool ShowMarker { get; set; }
public int MarkerSize { get; set; } = 4;
}
///
/// 快速构建一个Spline类型的ChartControl Series,X轴绑定时间类型的数据(目前还不支持多个series)
///
///
/// Chart顶部的标题
/// Y轴单位,默认无单位
/// Y轴数字保留的精度,默认3(只对double float类型的数据有效)
/// 时间格式字符
/// X轴时间显示的标签个数
/// 是否在Spline中显示点(如果绑定的数据点数少于3个,则始终会显示)
/// 该参数会使ChartControl创建多个Series,不含元素时也会创建一个
///
public static ChartControl UseSplineWithTimeData(this ChartControl ctrl, string chartTitle = "ChartTitle", string unitY = "", int yPrecision = 3, string xFormat = "yyyy-MM-dd HH:mm:ss", int xLableCount = 5, bool showMarker = false,string[] series=null)
{
ctrl.Titles.Clear();
ctrl.Titles.Add(new ChartTitle() { Text = chartTitle });
ctrl.Series.Clear();
if (series == null || !series.Any())
{
series = new string[1];
}
var options = new ChartOptions()
{
XLableCount = xLableCount,
ShowMarker = showMarker,
};
foreach (var item in series)
{
Series s = new Series();
s.CrosshairLabelPattern = "{A:" + xFormat + "}\r\n {V:f" + yPrecision + "}" + unitY;
s.Name = item;
s.ArgumentScaleType = ScaleType.DateTime;
SplineSeriesView splineSeriesView1 = new SplineSeriesView();
s.View = splineSeriesView1;
s.Tag = options;
ctrl.Series.Add(s);
}
var dt = new DateTime(2000, 2, 2, 1, 1, 1, 1);
var dtStr = dt.ToString(xFormat);
var dtNew = DateTime.ParseExact(dtStr, xFormat, null);
XYDiagram diagram = (XYDiagram)ctrl.Diagram;//坐标系设定
diagram.AxisX.Tickmarks.MinorVisible = false;
diagram.AxisY.Tickmarks.MinorVisible = false;
diagram.AxisX.Label.TextPattern = "{A:" + xFormat + "}";
diagram.AxisY.Label.TextPattern = "{V}" + unitY;
if (dtNew.Millisecond == 1)
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Millisecond;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Millisecond;
options.TimeType = EnumTimeType.Millisecond;
}
else if (dtNew.Second == 1)
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Second;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Second;
options.TimeType = EnumTimeType.Second;
}
else if (dtNew.Minute == 1)
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Minute;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Minute;
options.TimeType = EnumTimeType.Minute;
}
else if (dtNew.Hour == 1)
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Hour;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Hour;
options.TimeType = EnumTimeType.Hour;
}
else if (dtNew.Day == 2)
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Day;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Day;
options.TimeType = EnumTimeType.Day;
}
else if (dtNew.Month == 2)
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Month;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Month;
options.TimeType = EnumTimeType.Month;
}
else
{
diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Year;
diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Year;
options.TimeType = EnumTimeType.Year;
}
return ctrl;
}
///
/// 设置数据源
///
/// 泛型只支持基本数值类型
///
///
/// 要设置的series,默认会设置第一个series
///
public static ChartControl SetData(this ChartControl ctrl, IEnumerable<(DateTime x, T y)> data,string series=null)
{
var s = ctrl.Series.Where(p=>p.Name==series).FirstOrDefault() as Series;
if (s == null)
s = ctrl.Series.FirstOrDefault() as Series;
ChartOptions options = s.Tag as ChartOptions;
(s.View as SplineSeriesView).LineMarkerOptions.Size = options.MarkerSize;
if (data.Count() < 3)
(s.View as SplineSeriesView).MarkerVisibility = DevExpress.Utils.DefaultBoolean.True;
else
{
if (options.ShowMarker)
(s.View as SplineSeriesView).MarkerVisibility = DevExpress.Utils.DefaultBoolean.True;
else
(s.View as SplineSeriesView).MarkerVisibility = DevExpress.Utils.DefaultBoolean.False;
}
var yMin = data.Select(p => p.y).Min();
var yMax = data.Select(p => p.y).Max();
var xMin = data.Select(p => p.x).Min();
var xMax = data.Select(p => p.x).Max();
XYDiagram diagram = (XYDiagram)ctrl.Diagram;//坐标系设定
diagram.AxisY.WholeRange.SetMinMaxValues(yMin, yMax);
double gridSpacing = 0;
if (options.TimeType == EnumTimeType.Millisecond)
{
gridSpacing = (xMax - xMin).TotalMilliseconds / (options.XLableCount - 1);
}
else if (options.TimeType == EnumTimeType.Second)
{
gridSpacing = (xMax - xMin).TotalSeconds / (options.XLableCount - 1);
}
else if (options.TimeType == EnumTimeType.Minute)
{
gridSpacing = (xMax - xMin).TotalMinutes / (options.XLableCount - 1);
}
else if (options.TimeType == EnumTimeType.Hour)
{
gridSpacing = (xMax - xMin).TotalHours / (options.XLableCount - 1);
}
else if (options.TimeType == EnumTimeType.Day)
{
gridSpacing = (xMax - xMin).TotalDays / (options.XLableCount - 1);
}
else if (options.TimeType == EnumTimeType.Month)
{
gridSpacing = (xMax - xMin).TotalDays / 30d / (options.XLableCount - 1);
}
else if (options.TimeType == EnumTimeType.Year)
{
gridSpacing = (xMax - xMin).TotalDays / 365d / (options.XLableCount - 1);
}
if (gridSpacing > 0)
diagram.AxisX.DateTimeScaleOptions.GridSpacing = gridSpacing;
s.Points.AddRange(data.Select(p => new SeriesPoint(p.x, p.y)).ToArray());
return ctrl;
}
}
}