优劣势

ZedGraph 相较同类工具的优势:

  • 功能完备,bug 少
  • 用户基数大,Bing 搜问题方便

劣势:

  • 从 2012 后基本停止维护
  • 官网没了,对新上手的小伙伴不友好
    • 该问题可以通过浏览 ZedDemo.7z 中的示例项目得到解决

PS:虽然已停止维护快 10 年了,但还能被评为 14 个最好的 .NET 免费控件,希望能有更好的绘图库来替代 ZedGraph 的使命吧。

简介

ZedGraph 是一个强大的 .NET 图形绘制库。

The charting library for .NET

相关资源:

支持平台:

第一步:从控件库中拖一个 ZedGraphControl 到 Form 上。

第二步:通过代码初始化并绘制图形。

  1. private void Form1_Load( object sender, EventArgs e )
  2. {
  3. // Setup the graph
  4. CreateGraph( zedGraphControl1 );
  5. }
  6. // Build the Chart
  7. private void CreateGraph( ZedGraphControl zgc )
  8. {
  9. // get a reference to the GraphPane
  10. GraphPane myPane = zgc.GraphPane;
  11. // Set the Titles
  12. myPane.Title.Text = "My Test Graph\n(For CodeProject Sample)";
  13. myPane.XAxis.Title.Text = "My X Axis";
  14. myPane.YAxis.Title.Text = "My Y Axis";
  15. // Make up some data arrays based on the Sine function
  16. double x, y1, y2;
  17. PointPairList list1 = new PointPairList();
  18. PointPairList list2 = new PointPairList();
  19. for ( int i = 0; i < 36; i++ )
  20. {
  21. x = (double)i + 5;
  22. y1 = 1.5 + Math.Sin( (double)i * 0.2 );
  23. y2 = 3.0 * ( 1.5 + Math.Sin( (double)i * 0.2 ) );
  24. list1.Add( x, y1 );
  25. list2.Add( x, y2 );
  26. }
  27. // Generate a red curve with diamond
  28. // symbols, and "Porsche" in the legend
  29. LineItem myCurve = myPane.AddCurve( "Porsche",
  30. list1, Color.Red, SymbolType.Diamond );
  31. // Generate a blue curve with circle
  32. // symbols, and "Piper" in the legend
  33. LineItem myCurve2 = myPane.AddCurve( "Piper",
  34. list2, Color.Blue, SymbolType.Circle );
  35. // Tell ZedGraph to refigure the
  36. // axes since the data have changed
  37. zgc.AxisChange();
  38. }

效果:
ZedGraph 绘制图形 - 图1

使用技巧

给柱状图加数值标识

方法一,使用自带的 CreateBarLabels:

  1. BarItem.CreateBarLabels(myPane, false, "f0", "Arial", 28, Color.CadetBlue, false, false, false);

注:如果要清理这些 label,需要使用 zgc.GraphPane.GraphObjList.Clear();

方法二,手动绘制:

  1. var myPane = zgc.GraphPane;
  2. var fontSpec = myPane.Legend.FontSpec.Clone();
  3. fontSpec.Family = "Microsoft YaHei";
  4. fontSpec.Size = 22;
  5. fontSpec.Border.IsVisible = false;
  6. fontSpec.Fill.IsVisible = false;
  7. var text = new TextObj("2.33", 0.55, 2.33)
  8. {
  9. Location = { CoordinateFrame = CoordType.AxisXYScale, AlignH = AlignH.Left, AlignV = AlignV.Center },
  10. FontSpec = fontSpec
  11. };
  12. myPane.GraphObjList.Add(text);

修改右键菜单

参考 Edit the Context Menu

移除或禁用现有菜单项:

  1. private void MyContextMenuBuilder(
  2. ZedGraphControl control, ContextMenuStrip menuStrip,
  3. Point mousePt,ZedGraphControl.ContextMenuObjectState objState)
  4. {
  5. foreach( ToolStripMenuItem item in menuStrip.Items )
  6. {
  7. if ( (string) item.Tag == "set_default" )
  8. {
  9. // remove the menu item
  10. menuStrip.Items.Remove( item );
  11. // or, just disable the item with this
  12. //item.Enabled = false;
  13. break;
  14. }
  15. }
  16. }
StringID Menu Item
copy Copy
page_setup Page Setup…
print Print…
save_as Save Image As…
set_default Set Scale to Default
show_val Show Point Values
undo_all Undo All Zoom/Pan
unzoom Un-Zoom, Un-Pan, Undo Scroll

添加新的右键菜单项:

  1. private void MyContextMenuBuilder(
  2. ZedGraphControl control, ContextMenuStrip menuStrip,
  3. Point mousePt,ZedGraphControl.ContextMenuObjectState objState )
  4. {
  5. // create a new menu item
  6. ToolStripMenuItem item = new ToolStripMenuItem();
  7. // This is the user-defined Tag so you can find this menu item later if necessary
  8. item.Name = "my_special_tag";
  9. item.Tag = "my_special_tag";
  10. // This is the text that will show up in the menu
  11. item.Text = "Do Something Special";
  12. // Add a handler that will respond when that menu item is selected
  13. item.Click += new System.EventHandler( DoSomethingSpecial );
  14. // Add the menu item to the menu
  15. menuStrip.Items.Add( item );
  16. }
  17. protected void DoSomethingSpecial( object sender, System.EventArgs e )
  18. {
  19. // do something here. For example, remove all curves from the graph
  20. zedGraphControl1.GraphPane.CurveList.Clear();
  21. zedGraphControl1.Refresh();
  22. }

示例 - 右键菜单中增加导出为 CSV 功能

参考:ZedGraph C# Graph Data Export to CSV Using a Custom Context Menu

  1. private void InitializeZedGraph(ZedGraphControl zgc)
  2. {
  3. ...
  4. zgc.ContextMenuBuilder += Zgc_ContextMenuBuilder;
  5. }
  6. private void Zgc_ContextMenuBuilder(ZedGraphControl sender, ContextMenuStrip menuStrip, Point mousePt, ZedGraphControl.ContextMenuObjectState objState)
  7. {
  8. var item = new ToolStripMenuItem
  9. {
  10. Name = "Export Data as CSV",
  11. Tag = "export_data_csv",
  12. Text = "导出波形数据为 CSV"
  13. };
  14. item.Click += ShowSaveAsForExportCSV;
  15. menuStrip.Items.Insert(2, item);
  16. }
  17. private StreamWriter _csvWriter;
  18. private void ShowSaveAsForExportCSV(object sender, EventArgs e)
  19. {
  20. try
  21. {
  22. var dialogExportCSV = new SaveFileDialog
  23. {
  24. Filter = @"CSV Files|*.csv",
  25. Title = @"Export Profile",
  26. FileName = ZgcMain.GraphPane.Title.Text
  27. };
  28. if (dialogExportCSV.ShowDialog() != DialogResult.OK) return;
  29. _csvWriter = new StreamWriter(dialogExportCSV.FileName);
  30. WriteCSVToStream();
  31. _csvWriter.Close();
  32. MessageBox.Show("CSV 波形文件已保存", "波形导出", MessageBoxButtons.OK);
  33. }
  34. catch (Exception ex)
  35. {
  36. _csvWriter.Close();
  37. MessageBox.Show(ex.ToString());
  38. }
  39. }
  40. private void WriteCSVToStream()
  41. {
  42. var xAxisHeader = ZgcMain.GraphPane.XAxis.Title.Text;
  43. var yAxisHeader = ZgcMain.GraphPane.YAxis.Title.Text;
  44. _csvWriter.Write(xAxisHeader + "," + yAxisHeader + "\n");
  45. for (var i = 0; i < _currentPointList.Count; i++)
  46. {
  47. _csvWriter.Write(_currentPointList[i].X + "," + _currentPointList[i].Y + "\n");
  48. }
  49. }

获取当前点击的 Pane

当一个 Zed 上面有多个 Pane 时,可以用FinNearestPaneObject方法获取点击的 Pane。

当然该方法也可以用作获取其它 Object。

  1. using (var g = zed.CreateGraphics())
  2. {
  3. int iPt;
  4. GraphPane pane; object nearestObj;
  5. zed.MasterPane.FindNearestPaneObject(e.Location, g, out pane,out nearestObj,out iPt);
  6. pane.Border=new Border(Color.FromArgb(0,122,204),2);
  7. }

在一行并排显式两个 Pane

首先你要有两个 Pane,再通过SetLayout设置显式模式为SingleRow即可。

切换显式模式还可以得到 211、112、Square 等效果。

  1. var zed = ZedGraphMain;
  2. var master = zed.MasterPane;
  3. var leftPane = master.PaneList[0];
  4. var rightPane = leftPane.Clone();
  5. rightPane.CurveList.Clear();
  6. master.Add(rightPane);
  7. // Tell ZedGraph to auto layout all the panes
  8. using (var g = zed.CreateGraphics())
  9. {
  10. master.SetLayout(g, PaneLayout.SingleRow);
  11. master.AxisChange(g);
  12. }
  13. zed.AxisChange();
  14. zed.Refresh();