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; } } }