1.引言

由于工作原因,需要对数据进行图表展示,.NET默认的控件库或者DotNetBar的控件库又不能满足需求。去网上找到了这个开源的ZedGraph绘制2D图表的程序集,之所以选择这个ZedGraph程序集,一来它能够满足业务需求,二来它网上相关资料很多,三来它是开源代码。本篇中主要是给大家介绍几个我在开发过程中遇到的一些稍微棘手的问题,或者说是在网上资源较少的问题。在面对这些问题时,对于刚刚接触这个*.dll的我来说还是花了一些时间的,故而总结成篇。

2.相关资料

1.C# WinForm开发系列 - ZedGraph 
2.ZedGraph使用经验 
3.ZedGraph属性\方法介绍

相信认真参研上面的几篇博文,尤其是第一个之后,你对ZedGraph的入门使用会了解许多。如果你想更多的了解ZedGraph,可以Down下源码,仔细研究。ZedGraph的相对来说还是比较简单的,虽然说界面不甚美观,但其功能还算完善,我是做GIS二次开发的,它的几个基本功能:图表漫游、放大、缩小、上一视图等与GIS软件不谋而合。

3.ZedGraph节点Symbol问题

ZedGraph中有个枚举列举了节点的所有常见Symbol(如下),但是有些时候特殊问题特殊处理,我们需要用不同的symbol来表示节点,怎么办?
public enum SymbolType
{
Square,
Diamond,
Triangle,
Circle,
XCross,
Plus,
Star,
TriangleDown,
HDash,
VDash,
UserDefined,//用户自定义
Default,
None
}

参考如下Demo:ZedGraph自定义图标

4.ZedGraph上下文菜单问题

在开发过程中,如果需要实现图表的上下文菜单,需要将ZedGraphControl的IsShowContextMenu属性设置为true才可显示,当然你也可以实现自己的自定义上下文菜单。这里需要注意的是,有些你下载的dll可能上下菜单是中文,而有些却是英文并且有可能"缺损"了那么几项,造成这个问题的主要是由于ZedGraph开源,网友很有可能是改完源码之后上传的,这就造成你Down下来的dll不尽相同。现在的问题是:怎么修改ZedGraph的上下文菜单,英文<->中文?隐藏某一选项?代码如下:
private void zGCDateChart_ContextMenuBuilder(ZedGraphControl sender, ContextMenuStrip menuStrip, Point mousePt, ZedGraphControl.ContextMenuObjectState objState)
{
try
{
//每次循环只能遍历一个键
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "copy")
{
item.Text = "复制";
item.Visible = true;
break;
}
}
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "save_as")
{
item.Text = "另存图表";
item.Visible = true;
break;
}
} foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "show_val")
{
item.Text = "显示XY值";
item.Visible = true;
break;
}
}
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "unzoom")
{
item.Text = "上一视图";
item.Visible = true;
break;
}
}
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "undo_all")
{
item.Text = "还原缩放/移动";
item.Visible = true;
break;
}
}
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "print")
{
menuStrip.Items.Remove(item);
item.Visible = false; //不显示
break;
}
}
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "page_setup")
{
menuStrip.Items.Remove(item);//移除菜单项
item.Visible = false; //不显示
break;
}
}
foreach (ToolStripMenuItem item in menuStrip.Items)
{
if ((string)item.Tag == "set_default")
{
menuStrip.Items.Remove(item);//移除菜单项
item.Visible = false; //不显示
break;
}
} }
catch (System.Exception ex)
{
MessageBox.Show("初始化右键菜单错误" + ex.ToString());
}
}

这里需要注意几点:
1.事件为ContextMenuBuilder
2.每次foreach循环只能遍历一个键,因为你改变了枚举项。

5.添加文本问题

有些时候需要你在图表是添加一些文本,比如说:

TextObj text_obs = new TextObj("缩放:鼠标滚轮\n移动:鼠标中键\n菜单:鼠标右键", 0.899f, 0.001f, CoordType.ChartFraction, AlignH.Center, AlignV.Bottom);
text_obs.FontSpec.StringAlignment = StringAlignment.Center;
text_obs.FontSpec.Fill = new Fill(Color.LightBlue);
text_obs.FontSpec.FontColor = Color.Black;
myPane_obs.GraphObjList.Add(text_obs);

double xVal = Math.Round(list[i].X, 2);
double yVal = Math.Round(list[i].Y, 2);
string lab = string.Format("高潮位\r\n时间:{0}\r\n潮位:{1}", GetStrTime(xVal), yVal);
TextObj text = new TextObj(lab, (float)xVal, (float)yVal * 1.01);//设置一个偏移量
text.FontSpec.StringAlignment = StringAlignment.Near;
text.Location.CoordinateFrame = CoordType.AxisXYScale;//很重要,设置参考系,或者说参考坐标
text.FontSpec.Size = 10;
text.FontSpec.FontColor = Color.Blue;
text.Location.AlignH = AlignH.Center;
text.Location.AlignV = AlignV.Bottom;
text.FontSpec.Border.IsVisible = false;
text.FontSpec.Angle = 0;
text.FontSpec.Fill.IsVisible = false; myPane.GraphObjList.Add(text);

6.节点显示悬停提示和悬停提示闪烁问题

当你需要鼠标悬停在图表节点上提示节点的位置值,或者其他的一些内容时,你需要首先将ZedGraphControl的IsShowPointValues属性设置为true,然后关联事件PointValueEvent。
private string zGCDateChart_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt)
{
PointPair pt = curve[iPt];
return "时间:" + pt.X.ToString() + " \n潮位:" + pt.Y.ToString();
}
如果这样就把问题解决了,那固然好,可我在做的过程中发现的一个问题,或者说是不尽如人意的地方:当鼠标悬停在节点上时,内容是显示出来了,没有问题,但是悬停提示框就是一直在闪烁,这个问题困扰了我很久,解决方法如下:

找来ZedGraph的源码,在ZedGraphControl.Event.cs中找到了下面这块代码:
private Point HandlePointValues( Point mousePt )
{
int iPt;
GraphPane pane; object nearestObj;
using ( Graphics g = this.CreateGraphics() )
{
if ( _masterPane.FindNearestPaneObject( mousePt,g, out pane, out nearestObj, out iPt ) )
{
if ( nearestObj is CurveItem && iPt >= 0 )
{
//................ //code to show the tooltip
}
else
this.pointToolTip.Active = false;
}
else
this.pointToolTip.Active = false;
}
return mousePt;
}
分析后发现,原来这段代码不论鼠标移动的范围大小,甚至乎不论鼠标是否移动,都要刷新一次Tooltip,所以才会导致CPU爆满。

解决方案并不复杂,包括三个步骤:
1、创建私有变量lastObj用以保存上次为之显示Tooltip的对象;
2、显示Tooltip前判断对象是否就是lastObj;
3、将新获得的对象保存到lastObj中。
修改后的代码结构如下:
private object lastObj;
private Point HandlePointValues( Point mousePt )
{
int iPt;
GraphPane pane; object nearestObj;
using ( Graphics g = this.CreateGraphics() )
{
if ( _masterPane.FindNearestPaneObject( mousePtg, out pane, out nearestObj, out iPt ) )
{
if (nearestObj is CurveItem && iPt >= 0 && !object.Equals(nearestObj, lastObj))
{
//................ //code to show the tooltip
}
//else
// this.pointToolTip.Active = false;
}
else
this.pointToolTip.Active = false;
}
lastObj = nearestObj;
return mousePt;
}

7.X轴刻度重写(X轴刻度循环问题)

简单的X、Y轴刻度刻度形式可以通过设置以下属性来实现:
myPane_obs.XAxis.Scale.Format = "";
myPane_obs.YAxis.Scale.Format = "";

本次开发中碰到的是关于X轴循环问题,X轴是一根绝对的数轴,但是现实的数值代表时间,并且时间从0—23时不断重复循环,也就是说不会出现负数和大于23的整数,具体解决方案如下:

myPane_obs.XAxis.Scale.Min = 0;
myPane_obs.XAxis.Scale.Max = 24;
myPane_obs.XAxis.Scale.MajorStep = 4;
myPane_obs.XAxis.Scale.MinorStep = 1;
/// <summary>
/// X轴刻度重定义
/// </summary>
/// <param name="pane"></param>
/// <param name="axis"></param>
/// <param name="val"></param>
/// <param name="index"></param>
/// <returns></returns>
string XAxis_ScaleFormatEvent(GraphPane pane, Axis axis, double val, int index)
{
if (val >= 0 && val < 24)
return val.ToString();
else if (val >= 24)
return (val % 24).ToString();
else
return (24-Math.Abs(val % 24)).ToString();
}

关于ZedGraph几个难点的更多相关文章

  1. C#图表控件ZedGraph使用

    最近从java转到C#下开发PC端的桌面程序,之前也尝试用java GUI写桌面程序,发现java写桌面程序还是诸多不便变,虽然最后也写出来了,但是决心还是另起平台,有了一定的java基础,来学习C# ...

  2. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇二:基于OneNote难点突破和批量识别

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  3. Android开发重点难点1:RelativeLayout(相对布局)详解

    前言 啦啦啦~博主又推出了一个新的系列啦~ 之前的Android开发系列主要以完成实验的过程为主,经常会综合许多知识来写,所以难免会有知识点的交杂,给人一种混乱的感觉. 所以博主推出“重点难点”系列, ...

  4. Unity 难点目录

    1.mesh的任意切割.(难点) 2.扇形区域识别玩家.(解决) 3.NGUI横滑同时竖滑,或滑动同时点击冲突处理.(解决)

  5. 新浪微博SDK开发(2):上传图片的技术难点

    在微博模块中,有一个API是可以发表带一张图片的微博的,当然提交方式是POST.在封装的时候,可能会遇到一个难点——如何上传图片? 要POST微博的同时带有图片,POST的内容必须为MultiPart ...

  6. C# ZedGraph 控件各属性以及示例

    ZedGraph属性\方法介绍 Copy(Boolean) ->> 将图像复制到剪贴板.DoPageSetup()() ->> 打开打印设置对话框. DoPrint()() - ...

  7. .NET_RSA加密全接触(重、难点解析)

    .NET_RSA加密全接触(重.难点解析) .NET Framework提供了两个类供我们使用RSA算法,分别是:用于加密数据的RSACryptoServiceProvider和用于数字签名的DSAC ...

  8. js 函数闭包内部返回函数体调用方法难点解答

    今天在网上,看到一篇关于js函数难点的文章,js函数的一些难点.在那上面提了一下,关于js函数返回另一个函数的问题,并附上了一道面试题: var add = function(x){ var sum ...

  9. C# WinForm开发系列 - ZedGraph

    ZedGraph是用于创建任意数据的二维线型.条型.饼型图表的一个类库,也可以作为Windows窗体用户控件和Asp.Net网页控件.这个类库具有高度的适应性,几乎所有式样的图表都能够被创建.这个类库 ...

随机推荐

  1. [Winform]CefSharp ——js调用c#方法

    摘要 有时我们在winform中嵌入浏览器,需要在页面上读取电脑上的一些信息,这个时候就需要用到CefSharp的RegisterJsObject进行注册方法然后供js进行调用了. 一个例子 我们在w ...

  2. .Net Discovery 系列之七--深入理解.Net垃圾收集机制(拾贝篇)

    关于.Net垃圾收集器(Garbage Collection),Aicken已经在“.Net Discovery 系列”文章中有2篇的涉及,这一篇文章是对上2篇文章的补充,关于“.Net Discov ...

  3. 快速打开 Mac OS X 隐藏的用户资源库文件夹

    在较高版本的 Mac OS X 中,用户的资源库文件夹(/Users/username/Library)默认被系统隐藏了,从 Finder 窗口中不能直接打开. 下面介绍一个非常简单的方法来快速打开用 ...

  4. Noip2005谁拿了最多的奖学金题解

    题解 题目本身没什么好说的. 只是一道普及组的题让我领悟到scanf()读字符的真谛.scanf()函数最奇异的功能就是控制串里除格式化字符串之外的字符.若匹配成功则舍去. 所以我们能够"精 ...

  5. 在Visual Studio中使用组件图描述项目组件依赖关系

    如果想描述项目组件的关系,可以考虑使用UML组建图. 在建模项目下添加一个名称为"Applicaiton Component Structure"的UML组建图. 添加各个组件,并 ...

  6. 得到WAV文件的长度

    long getVideoLength (char *fileName){   MCI_OPEN_PARMS mciOpenParms;   MCI_STATUS_PARMS mciStatusPar ...

  7. iOS越狱知多少?

    著名iOS黑客团队Evad3rs上周上线了evasi0n 官网,用于展示他们破解iOS 6 和iOS 6.1  系统的进度.据官网显示,其越狱工具evasi0n已正式上线,支持iPhone.iPad等 ...

  8. linux下一个网卡配置多个IP

    转自:http://blog.csdn.net/beckdon/article/details/15815197 最常用的给网卡配置ip的命令为 #ifconfig eth0 192.168.0.1 ...

  9. JAVA 解压压缩包中指定文件或实现压缩文件的预览及下载单个或多个指定的文件

    业务逻辑中还要判读用户是否有此文件的防问权限 2017-04-20 新增文件与文件夹图标显示及过滤高亮显示功能: 2017-05-20 新增搜索向前及向后.及更新下载功能.更新文件路径显示: 测试地址 ...

  10. ios成长之每日一遍(day 7)

    今天到UITabBarController 结合 UIPickView, 这里一共有5个实现, 由浅到易. 其实在IB上面使用UITabBarController很简单, 就像平常拖控件一样拖到界面上 ...