【WinForm】ChartControl 使用汇总
一、外观属性汇总
以下均以横坐标举例,纵坐标同理,把AxisX换成AxisY就可以了。
参考官网:Grid Spacing | WinForms Controls | DevExpress Documentation
1、使横坐标只显示刻度不显示对应值
AxisX.Label.Visible
2、改变横坐标一格精度
(1)主刻度值
AxisX.NumericScaleOption.Gridspacing=500;
对于数字轴,GridSpacing和GridAlignment属性值同时使用时,它们会相乘,结果定义网格步长,例如:
GridSpacing = 5; GridAlignment = NumericGridAlignment.Hundreds
和
GridSpacing = 500; GridAlignment = NumericGridAlignment.Ones
效果一样。
(2)两个主要刻度线之间的刻度线数
AxisX.MinorCount=4;
相同的值指定网格线的数量。
3、隐藏坐标刻度和值
AxisX.Visible
4、改变一屏显示范围值
AxisX.VisualRange.MaxValue
AxisX.VisualRange.MinValue
5、显示横坐标滚动条
注:多纵轴时也只有一个滚动条。
XYDiagram.DefaultPane.ScrollBarOptions.XaxisScrollBarVisible
6、设置图表可滚轮缩放
XYDiagram diagram = (XYDiagram)ChartControl.Diagram;
diagram.EnableAxisXScrolling = true;
diagram.EnableAxisYScrolling = false;
diagram.EnableAxisXZooming = true;
diagram.EnableAxisYZooming = true;
7、自定义十字线显示Y轴数据格式
想要保留两位小数,但double类型会自动除掉无效的尾0(比如1.70直接显示1.7),故只能从Y轴数据格式入手。
配置Label.TextPattern属性,效果如下:
XYDiagram diagram = (XYDiagram)WaveChartControl.Diagram; if (diagram != null) { diagram.AxisY.Label.TextPattern = "{V:#.00}"; }
可见Label格式生效了,但Crosshair还是没有保留两位小数。看属性里有个CrosshairAxisLabelOptions.Pattern参数,好像很像,故配置:
diagram.AxisY.CrosshairAxisLabelOptions.Pattern = "{V:#.00}";
但测试证明这个对Crosshair没起作用...不知道是啥。最终配置下方属性达到了效果:
WaveChartControl.Series[ch].CrosshairLabelPattern = "{V:#.00}";
代码参考:https://blog.csdn.net/qq_36905714/article/details/120327214
Pattern格式参考:https://docs.devexpress.com/CoreLibraries/DevExpress.XtraCharts.SeriesBase.CrosshairLabelPattern
二、编程实例
添加正弦曲线:
/// <summary> /// 添加曲线 /// </summary> /// <param name="SignalName">曲线名称</param> /// <param name="YOffset">控件Y坐标</param> private void AddWave(string SignalName, double YOffset) { Series series = new Series(SignalName, ViewType.Spline); //Color CurrentColor = GetRandomColor(); //while (CurrentColor == HistoryColor) //避免获取相同颜色 //{ // CurrentColor = GetRandomColor(); // HistoryColor = CurrentColor; //} //series.View.Color = CurrentColor; WaveChartControl.Series.Add(series);//添加曲线 ///设置图表Y轴 XYDiagram diagram = (XYDiagram)WaveChartControl.Diagram; diagram.AxisY.WholeRange.MaxValue = WholeRangeMaxValue = 5; diagram.AxisY.WholeRange.MinValue = -5; diagram.AxisY.VisualRange.MaxValue = 5; diagram.AxisY.VisualRange.MinValue = -5; diagram.AxisY.WholeRange.SideMarginsValue = 0; //最外层点与图表边缘间距 diagram.AxisY.VisualRange.SideMarginsValue = 0; ///设置图表可滚轮缩放 diagram.EnableAxisXScrolling = true; diagram.EnableAxisYScrolling = false; diagram.EnableAxisXZooming = true; diagram.EnableAxisYZooming = true; ///添加曲线点 ////方法1:逐个添加Points,大数据量时速度慢 //for (int j = 0; j < 10000; j++) //{ // WaveChartControl.Series[SelectList.Count - 1].Points.AddPoint(j, 0); // double OriginalValue = Math.Sin(j * Math.PI / 180.0);//画正弦 // WaveChartControl.Series[SelectList.Count - 1].Points[j].Values[0] = OriginalValue; //} ////方法2:直接绑定数据源,速度快 ArrayList tmplistDataSource = new ArrayList(); for (int j = 0; j < 10000; j++) { double OriginalValue = Math.Sin(j * Math.PI / 180.0);//画正弦 tmplistDataSource.Add(new Record(j, j, OriginalValue)); } listDataSource.Add(tmplistDataSource); //数据源绑定 //WaveChartControl.DataSource = listDataSource; WaveChartControl.Series[SelectList.Count - 1].DataSource = listDataSource[listDataSource.Count - 1]; WaveChartControl.Series[SelectList.Count - 1].ArgumentDataMember = "XData"; WaveChartControl.Series[SelectList.Count - 1].ValueDataMembers.AddRange(new string[] { "YData" }); ((BarSeriesView)WaveChartControl.Series[SelectList.Count - 1].View).ColorEach = true; //WaveChartControl.Series[SelectList.Count - 1].LegendTextPattern = "{A}"; }
Record类:
public class Record { int id, xData; double yData; public Record(int id, int xData, double yData) { this.id = id; this.xData = xData; this.yData = yData; } public int ID { get { return id; } set { id = value; } } public int XData { get { return xData; } set { xData = value; } } public double YData { get { return yData; } set { yData = value; } } }
三、多Y轴设计
1、https://www.cnblogs.com/amw2738/p/3734798.html
2、https://www.cnblogs.com/sumuncle/p/5620844.html
四、判断鼠标是否悬停在坐标轴上
private void WaveChartControl_MouseMove(object sender, MouseEventArgs e) { ChartHitInfo hi = WaveChartControl.CalcHitInfo(new System.Drawing.Point(e.X, e.Y)); ///判断鼠标是否悬停在坐标轴上 if (hi.Axis != null) { if (hi.Axis.Name.Contains("AxisX"))//鼠标停在X轴上 { } else//鼠标停在Y轴上 { } } }
同理可通过ChartHitInfo判断鼠标是否停在图表区域等。
五、重写鼠标滚轮缩放功能
由于ChartControl同时开启 EnableAxisXZooming 和 EnableAxisYZooming 时,滚动滚轮会使X轴和Y轴同时产生缩放。以下代码可实现鼠标停在X轴上时,缩放X轴;鼠标停在Y轴上时,缩放Y轴。
事件绑定:
bool EnableAxisXZooming = false;///全局 bool EnableAxisYZooming = false; WaveChartControl.ObjectHotTracked += new DevExpress.XtraCharts.HotTrackEventHandler(this.WaveChartControl_ObjectHotTracked); WaveChartControl.MouseMove += new System.Windows.Forms.MouseEventHandler(this.WaveChartControl_MouseMove); ///鼠标滚轮事件,在控件属性中没有MouseWheel事件,只能手动代码里添加 WaveChartControl.MouseWheel += new MouseEventHandler(WaveChartControl_MouseWheel);
功能函数: private void WaveChartControl_MouseWheel(object sender, MouseEventArgs e)
{ MouseWheel(e.Delta); } private void WaveChartControl_MouseMove(object sender, MouseEventArgs e) { ChartHitInfo hi = WaveChartControl.CalcHitInfo(new System.Drawing.Point(e.X, e.Y)); ///判断鼠标是否悬停在坐标轴上 if (hi.Axis != null) { if (hi.Axis.Name.Contains("AxisX"))//鼠标停在X轴上 { ///设置图表可滚轮缩放 EnableAxisXZooming = true; EnableAxisYZooming = false; } else//鼠标停在Y轴上 { EnableAxisXZooming = false; EnableAxisYZooming = true; } } else { EnableAxisXZooming = false; EnableAxisYZooming = false; } } private void WaveChartControl_ObjectHotTracked(object sender, HotTrackEventArgs e) { ///必须添加这个事件才能在触发WaveChartControl_MouseMove时使Axis不为Null?
///如果添加了十字线,貌似会看到十字线出现时有些卡顿 } /// <summary> /// 鼠标滚轮缩放操作 /// </summary> /// <param name="Delta"></param> private void MouseWheel(int Delta) { XYDiagram diagram = (XYDiagram)WaveChartControl.Diagram; if (diagram != null) { if (diagram.AxisY != null && EnableAxisYZooming) { var direction = Delta < 1 ? -0.05f : 0.05f; double VisualMax = (double)diagram.AxisY.VisualRange.MaxValue; double VisualMin = (double)diagram.AxisY.VisualRange.MinValue; var increment = direction * (VisualMax - VisualMin); var newMin = VisualMin + increment; var newMax = VisualMax - increment; diagram.AxisY.VisualRange.MaxValue = newMax; diagram.AxisY.VisualRange.MinValue = newMin; } else if (diagram.AxisX != null && EnableAxisXZooming) { var direction = Delta < 1 ? -0.05f : 0.05f; double VisualMax = (double)diagram.AxisX.VisualRange.MaxValue; double VisualMin = (double)diagram.AxisX.VisualRange.MinValue; var increment = direction * (VisualMax - VisualMin); var newMin = VisualMin + increment; var newMax = VisualMax - increment; diagram.AxisX.VisualRange.MaxValue = newMax; diagram.AxisX.VisualRange.MinValue = newMin; } } }
六、鼠标移动到图表时,显示提示信息
ChartControl.RuntimeHitTesting属性一定要设为True。
Line Series markers的Visible一定要弄成True。CalcHitInfo的SeriesPoint一直为null,最后跑到devexpress support center上问的。我的dev版本是13.1.5,设置属性的方法是Series->View->MarkerVisibility。有的版本可能是Series -> LineMarkerOptions -> Visible。
我的是以曲线图Spline为例,下面就是代码。
1、鼠标点击点弹出Messagebox
private void chartControl4_MouseClick(object sender, MouseEventArgs e) { ChartHitInfo hitInfo = chartControl4.CalcHitInfo(e.Location); if (hitInfo.SeriesPoint != null) { MessageBox.Show(hitInfo.SeriesPoint.Values[0].ToString()); } }
2、鼠标移动用ToolTipController显示值
ToolTipController toolTipController = new ToolTipController(); private void chartControl4_MouseMove(object sender, MouseEventArgs e) { ChartHitInfo hitInfo = chartControl4.CalcHitInfo(e.Location); StringBuilder builder = new StringBuilder(); if (hitInfo.InDiagram) builder.AppendLine("In diagram"); if (hitInfo.InNonDefaultPane) builder.AppendLine("In non-default pane: " + hitInfo.NonDefaultPane.Name); if (hitInfo.InAxis) { builder.AppendLine("In axis: " + hitInfo.Axis.Name); if (hitInfo.AxisLabelItem != null) builder.AppendLine(" Label item: " + hitInfo.AxisLabelItem.Text); if (hitInfo.AxisTitle != null) builder.AppendLine(" Axis title: " + hitInfo.AxisTitle.Text); } if (hitInfo.InChartTitle) builder.AppendLine("In chart title: " + hitInfo.ChartTitle.Text); if (hitInfo.InLegend) builder.AppendLine("In legend"); if (hitInfo.InSeries) builder.AppendLine("In series: " + ((Series)hitInfo.Series).Name); if (hitInfo.InSeriesLabel) { builder.AppendLine("In series label"); builder.AppendLine(" Series: " + ((Series)hitInfo.Series).Name); } if (hitInfo.SeriesPoint != null) { builder.AppendLine(" Argument: " + hitInfo.SeriesPoint.Argument); if (!hitInfo.SeriesPoint.IsEmpty) builder.AppendLine(" Value: " + hitInfo.SeriesPoint.Values[0]); } if (builder.Length > 0) toolTipController.ShowHint("Hit-testing results:\n" + builder.ToString(), chartControl4.PointToScreen(e.Location)); else toolTipController.HideHint(); } private void chartControl4_MouseLeave(object sender, EventArgs e) { toolTipController.HideHint(); }
3、另一种鼠标移动显示信息的方法,用CustomDrawCrosshair事件,从别人那里学习的。这种还可以显示图片。
private void chartControl4_CustomDrawCrosshair(object sender, CustomDrawCrosshairEventArgs e) { foreach (CrosshairElement element in e.CrosshairElements) { SeriesPoint point = element.SeriesPoint; element.LabelElement.MarkerImage = Image.FromFile(@"F:\Resources\Add.png");// 设置图片路径 element.LabelElement.MarkerImageSizeMode = ChartImageSizeMode.Stretch; element.LabelElement.MarkerSize = new Size(100, 100); // 大小 element.LabelElement.Text = point.Values[0].ToString();//显示要显示的文字 } }
来源:https://blog.csdn.net/hyj_13/article/details/22416029
柱状图示例:https://blog.csdn.net/sinat_15155817/article/details/48527295
七、添加基准线
/// <summary> /// 创建基准线ConstantLine /// </summary> /// <param name="chart">ChartControl</param> /// <param name="ctAxisValue">基准线数值</param> /// <param name="ctLegendText">基准线图例文字</param> /// <param name="ctTitle">基准线文字</param> /// <param name="ctTitleColor">基准线字体颜色</param> /// <param name="ctLineColor">基准线颜色</param> /// <param name="ctLineStyle">基准线样式</param> public static void CreateConstantLine(this ChartControl chart, int ctAxisValue, string ctLegendText, string ctTitle, Color ctTitleColor, Color ctLineColor, DashStyle ctLineStyle) { XYDiagram _diagram = (XYDiagram)chart.Diagram; if (_diagram != null) { ConstantLine _ctLine = new ConstantLine(); _ctLine.AxisValue = ctAxisValue; _ctLine.Visible = true; _ctLine.ShowInLegend = true; _ctLine.LegendText = ctLegendText; _ctLine.ShowBehind = false; _ctLine.Title.Visible = true; _ctLine.Title.Text = ctTitle; _ctLine.Title.TextColor = ctTitleColor; _ctLine.Title.Antialiasing = false; _ctLine.Title.Font = new Font("Tahoma", 14, FontStyle.Bold); _ctLine.Title.ShowBelowLine = true; _ctLine.Title.Alignment = ConstantLineTitleAlignment.Far; _ctLine.Color = ctLineColor; _ctLine.LineStyle.DashStyle = ctLineStyle; _ctLine.LineStyle.Thickness = 2; _diagram.AxisY.ConstantLines.Add(_ctLine); } }
调用:
chartControl1.CreateConstantLine(25, "理论利润", "理论利润", Color.Red, Color.Red, DashStyle.Dash);
出处:https://www.bbsmax.com/A/8Bz8VQbo5x/
八、获取当前十字准线显示的点的值
private void ChartControl_CustomDrawCrosshair(object sender, CustomDrawCrosshairEventArgs e) { foreach (CrosshairElementGroup elementGroup in e.CrosshairElementGroups) { if(elementGroup.CrosshairElements.Count > 0) { var SeriesPoint = elementGroup.CrosshairElements[0].SeriesPoint; if (SeriesPoint != null) { CurrentTime = Convert.ToDouble(SeriesPoint.Argument); ZoomValid = true; break; } } } }
九、取消曲线的自动平滑效果
设置LineTensionPercent :获取或设置用于绘制样条曲线的线张力,以百分比表示。设置的值越大,线条越圆滑 ,极限是100。
Series series = new Series(string.Format("通道{0}", i + 1), ViewType.Spline); ((SplineSeriesView)series.View).LineTensionPercent = 10;
参考:https://blog.csdn.net/HobbyFull/article/details/112357765
十、问题汇总
1、XYDiagram一直为null
(1)图标里必须添加一条Series;
(2)至少有一条Series的Visible属性不为false。
2、绑定DataSource修改数据时不刷新
先给chartcontrol解绑,然后更新完数据之后再绑定:
chart1.DataSource = null; chart1.DataSource = Points1;
3、X轴不从0开始
XYDiag.AxisX.VisualRange.SideMarginsValue = 0;
XYDiag.AxisX.WholeRange.SideMarginsValue = 0;
XYDiag.AxisX.VisualRange.AutoSideMargins = false;
XYDiag.AxisX.WholeRange.AutoSideMargins = false;
十一、显示数据点标签
series1.LabelsVisibility = DevExpress.Utils.DefaultBoolean.True; series1.Label.TextPattern = "({A},{V})";
Pattern格式参考:https://docs.devexpress.com/CoreLibraries/DevExpress.XtraCharts.SeriesBase.CrosshairLabelPattern
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步