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. 【shell学习笔记】curl命令总结

    2014-12-16 20:34 文思海辉 =========== CURL命令总结 1. 下载 curl -o [文件名称] www.baidu.com 2. 显示 HTTP request头信息 ...

  2. 如何让PictureBox背景色透明

    winform程序中的PictureBox载入了一张带有透明度的PNG图片,悬浮于其他控件之上,但是它的背景不是透明的,即使把它的BackColor设置为Color.Transparent,或者是0x ...

  3. showplan_text查询计划查询 sql执行顺序 时间 IO

    http://www.cnblogs.com/happyday56/archive/2009/09/10/1564144.html   set showplan_text ongoselect exp ...

  4. YUI-compressor 在Linux下安装和使用

    介绍一个非常流行的javascript压缩工具YUI compressor,可以提供更好的压缩效率:该工具由著名的Yahoo Exceptional Performance项目组出品. JSMin非常 ...

  5. UINavigationController 、UINavigationBar 、UINavigationItem 超清晰直观详解(扩展)

    ios开发中如何隐藏各种bar 状态条Status Bar [UIApplication sharedApplication].statusBarHidden = YES; 或者 // iOS3.2+ ...

  6. 设计模式之代理模式之二(Proxy)

    from://http://www.cnblogs.com/xwdreamer/archive/2012/05/23/2515306.html 设计模式之代理模式之二(Proxy)   0.前言 在前 ...

  7. WordPress主题开发:网站搜索

    调用方法一:手动输入html <form role="search" method="get" id="searchform" act ...

  8. Java并发编程的艺术(八)——闭锁、同步屏障、信号量详解

    1. 闭锁:CountDownLatch 1.1 使用场景 若有多条线程,其中一条线程需要等到其他所有线程准备完所需的资源后才能运行,这样的情况可以使用闭锁. 1.2 代码实现 // 初始化闭锁,并设 ...

  9. 凝聚法层次聚类之ward linkage method

    凝聚法分层聚类中有一堆方法可以用来算两点(pair)之间的距离:欧式,欧式平方,manhattan等,还有一堆方法可以算类(cluster)与类之间的距离,什么single-linkage.compl ...

  10. protobuf示例

    Google protobuf 是一个高性能的序列化结构化数据存储格式的接口描述语言,具有多语言支持,协议数据小,方便传输,高性能等特点.通过将结构化数据序列化(串行化)成二进制数组,并将二进制数组反 ...