【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

posted @   不溯流光  阅读(2238)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示