ChartExtension.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using DevExpress.Charts.Native;
  2. using DevExpress.Utils.Extensions;
  3. using DevExpress.XtraCharts;
  4. using DevExpress.XtraEditors;
  5. using DevExpress.XtraLayout;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Drawing;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. namespace ExtensionsDev
  14. {
  15. public static class ChartExtension
  16. {
  17. private enum EnumTimeType
  18. {
  19. Year,
  20. Month,
  21. Day,
  22. Hour,
  23. Minute,
  24. Second,
  25. Millisecond
  26. }
  27. private class ChartOptions
  28. {
  29. public int XLableCount { get; set; } = 5;
  30. public EnumTimeType TimeType { get; set; } = EnumTimeType.Second;
  31. public bool ShowMarker { get; set; }
  32. public int MarkerSize { get; set; } = 4;
  33. }
  34. /// <summary>
  35. /// 快速构建一个Spline类型的ChartControl Series,X轴绑定时间类型的数据(目前还不支持多个series)
  36. /// </summary>
  37. /// <param name="ctrl"></param>
  38. /// <param name="chartTitle">Chart顶部的标题</param>
  39. /// <param name="unitY">Y轴单位,默认无单位</param>
  40. /// <param name="yPrecision">Y轴数字保留的精度,默认3(只对double float类型的数据有效)</param>
  41. /// <param name="xFormat">时间格式字符</param>
  42. /// <param name="xLableCount">X轴时间显示的标签个数</param>
  43. /// <param name="showMarker">是否在Spline中显示点(如果绑定的数据点数少于3个,则始终会显示)</param>
  44. /// <param name="series">该参数会使ChartControl创建多个Series,不含元素时也会创建一个</param>
  45. /// <returns></returns>
  46. 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)
  47. {
  48. ctrl.Titles.Clear();
  49. ctrl.Titles.Add(new ChartTitle() { Text = chartTitle });
  50. ctrl.Series.Clear();
  51. if (series == null || !series.Any())
  52. {
  53. series = new string[1];
  54. }
  55. var options = new ChartOptions()
  56. {
  57. XLableCount = xLableCount,
  58. ShowMarker = showMarker,
  59. };
  60. foreach (var item in series)
  61. {
  62. Series s = new Series();
  63. s.CrosshairLabelPattern = "{A:" + xFormat + "}\r\n {V:f" + yPrecision + "}" + unitY;
  64. s.Name = item;
  65. s.ArgumentScaleType = ScaleType.DateTime;
  66. SplineSeriesView splineSeriesView1 = new SplineSeriesView();
  67. s.View = splineSeriesView1;
  68. s.Tag = options;
  69. ctrl.Series.Add(s);
  70. }
  71. var dt = new DateTime(2000, 2, 2, 1, 1, 1, 1);
  72. var dtStr = dt.ToString(xFormat);
  73. var dtNew = DateTime.ParseExact(dtStr, xFormat, null);
  74. XYDiagram diagram = (XYDiagram)ctrl.Diagram;//坐标系设定
  75. diagram.AxisX.Tickmarks.MinorVisible = false;
  76. diagram.AxisY.Tickmarks.MinorVisible = false;
  77. diagram.AxisX.Label.TextPattern = "{A:" + xFormat + "}";
  78. diagram.AxisY.Label.TextPattern = "{V}" + unitY;
  79. if (dtNew.Millisecond == 1)
  80. {
  81. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Millisecond;
  82. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Millisecond;
  83. options.TimeType = EnumTimeType.Millisecond;
  84. }
  85. else if (dtNew.Second == 1)
  86. {
  87. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Second;
  88. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Second;
  89. options.TimeType = EnumTimeType.Second;
  90. }
  91. else if (dtNew.Minute == 1)
  92. {
  93. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Minute;
  94. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Minute;
  95. options.TimeType = EnumTimeType.Minute;
  96. }
  97. else if (dtNew.Hour == 1)
  98. {
  99. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Hour;
  100. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Hour;
  101. options.TimeType = EnumTimeType.Hour;
  102. }
  103. else if (dtNew.Day == 2)
  104. {
  105. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Day;
  106. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Day;
  107. options.TimeType = EnumTimeType.Day;
  108. }
  109. else if (dtNew.Month == 2)
  110. {
  111. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Month;
  112. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Month;
  113. options.TimeType = EnumTimeType.Month;
  114. }
  115. else
  116. {
  117. diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Year;
  118. diagram.AxisX.DateTimeScaleOptions.GridAlignment = DateTimeGridAlignment.Year;
  119. options.TimeType = EnumTimeType.Year;
  120. }
  121. return ctrl;
  122. }
  123. /// <summary>
  124. /// 设置数据源
  125. /// </summary>
  126. /// <typeparam name="T">泛型只支持基本数值类型</typeparam>
  127. /// <param name="ctrl"></param>
  128. /// <param name="data"></param>
  129. /// <param name="series">要设置的series,默认会设置第一个series</param>
  130. /// <returns></returns>
  131. public static ChartControl SetData<T>(this ChartControl ctrl, IEnumerable<(DateTime x, T y)> data,string series=null)
  132. {
  133. var s = ctrl.Series.Where(p=>p.Name==series).FirstOrDefault() as Series;
  134. if (s == null)
  135. s = ctrl.Series.FirstOrDefault() as Series;
  136. ChartOptions options = s.Tag as ChartOptions;
  137. (s.View as SplineSeriesView).LineMarkerOptions.Size = options.MarkerSize;
  138. if (data.Count() < 3)
  139. (s.View as SplineSeriesView).MarkerVisibility = DevExpress.Utils.DefaultBoolean.True;
  140. else
  141. {
  142. if (options.ShowMarker)
  143. (s.View as SplineSeriesView).MarkerVisibility = DevExpress.Utils.DefaultBoolean.True;
  144. else
  145. (s.View as SplineSeriesView).MarkerVisibility = DevExpress.Utils.DefaultBoolean.False;
  146. }
  147. var yMin = data.Select(p => p.y).Min();
  148. var yMax = data.Select(p => p.y).Max();
  149. var xMin = data.Select(p => p.x).Min();
  150. var xMax = data.Select(p => p.x).Max();
  151. XYDiagram diagram = (XYDiagram)ctrl.Diagram;//坐标系设定
  152. diagram.AxisY.WholeRange.SetMinMaxValues(yMin, yMax);
  153. double gridSpacing = 0;
  154. if (options.TimeType == EnumTimeType.Millisecond)
  155. {
  156. gridSpacing = (xMax - xMin).TotalMilliseconds / (options.XLableCount - 1);
  157. }
  158. else if (options.TimeType == EnumTimeType.Second)
  159. {
  160. gridSpacing = (xMax - xMin).TotalSeconds / (options.XLableCount - 1);
  161. }
  162. else if (options.TimeType == EnumTimeType.Minute)
  163. {
  164. gridSpacing = (xMax - xMin).TotalMinutes / (options.XLableCount - 1);
  165. }
  166. else if (options.TimeType == EnumTimeType.Hour)
  167. {
  168. gridSpacing = (xMax - xMin).TotalHours / (options.XLableCount - 1);
  169. }
  170. else if (options.TimeType == EnumTimeType.Day)
  171. {
  172. gridSpacing = (xMax - xMin).TotalDays / (options.XLableCount - 1);
  173. }
  174. else if (options.TimeType == EnumTimeType.Month)
  175. {
  176. gridSpacing = (xMax - xMin).TotalDays / 30d / (options.XLableCount - 1);
  177. }
  178. else if (options.TimeType == EnumTimeType.Year)
  179. {
  180. gridSpacing = (xMax - xMin).TotalDays / 365d / (options.XLableCount - 1);
  181. }
  182. if (gridSpacing > 0)
  183. diagram.AxisX.DateTimeScaleOptions.GridSpacing = gridSpacing;
  184. s.Points.AddRange(data.Select(p => new SeriesPoint(p.x, p.y)).ToArray());
  185. return ctrl;
  186. }
  187. }
  188. }