使用InteractiveDataDisplay.WPF导出图像时系列未正常显示求助
解决InteractiveDataDisplay.WPF导出图表时Series不显示的问题
嘿,我看到你遇到了用InteractiveDataDisplay.WPF生成图表正常,但导出为图像时折线系列(Series)消失的问题,咱们来拆解一下原因和解决办法:
问题根源
你代码里的核心问题在于WPF中一个UI元素不能同时属于两个可视化树。你原本的lines Grid已经是原plotter Chart的子元素了,当你直接把它赋值给新创建的Bmain_Chart.Content时,WPF会自动将lines从原plotter的可视化树中移除,但这个过程并没有正确触发LineGraph的布局和渲染逻辑,导致新Chart渲染时无法显示这些折线系列。
解决方案
这里提供两种可行的解决思路:
方案一:直接渲染原有的Chart控件(推荐)
既然原界面的图表显示正常,我们可以直接渲染原有的plotter(或者它的父容器Grafico),不需要新建Chart实例。这样能完整保留所有已绘制的Series:
修改后的代码如下:
public MainWindow() { InitializeComponent(); double[] x = new double[200]; for (int i = 0; i < x.Length; i++) x[i] = 3.1415 * i / (x.Length - 1); for (int i = 0; i < 25; i++) { var lg = new LineGraph(); lines.Children.Add(lg); lg.Stroke = new SolidColorBrush(Color.FromArgb(255, 0, (byte)(i * 10), 0)); lg.Description = String.Format("Data series {0}", i + 1); lg.StrokeThickness = 2; lg.Plot(x, x.Select(v => Math.Sin(v + i / 10.0)).ToArray()); } int width = 800; int height = 600; // 给原plotter设置需要的标题(如果需要保留原界面标题,可以先保存再恢复) var originalLeftTitle = plotter.LeftTitle; var originalBottomTitle = plotter.BottomTitle; plotter.LeftTitle = "Bmain"; plotter.BottomTitle = "Time"; // 测量并排列原plotter控件,确保布局完成 plotter.Measure(new Size(width, height)); plotter.Arrange(new Rect(new Size(width, height))); plotter.UpdateLayout(); // 渲染并导出 RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); bmp.Render(plotter); var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); using (Stream stm = File.Create(@"c:\MyCustomPath\test.png")) { encoder.Save(stm); } // 恢复原界面的标题(可选) plotter.LeftTitle = originalLeftTitle; plotter.BottomTitle = originalBottomTitle; }
方案二:重新创建Series到新Chart中
如果你确实需要创建新的Chart实例来导出,不要复用原有的lines容器,而是重新创建所有LineGraph并添加到新Chart中:
public MainWindow() { InitializeComponent(); double[] x = new double[200]; for (int i = 0; i < x.Length; i++) x[i] = 3.1415 * i / (x.Length - 1); // 先在原界面绘制图表 for (int i = 0; i < 25; i++) { var lg = new LineGraph(); lines.Children.Add(lg); lg.Stroke = new SolidColorBrush(Color.FromArgb(255, 0, (byte)(i * 10), 0)); lg.Description = String.Format("Data series {0}", i + 1); lg.StrokeThickness = 2; lg.Plot(x, x.Select(v => Math.Sin(v + i / 10.0)).ToArray()); } int width = 800; int height = 600; // 创建新Chart并重新添加所有Series Chart Bmain_Chart = new Chart(); Bmain_Chart.LeftTitle = "Bmain"; Bmain_Chart.BottomTitle = "Time"; // 创建新的容器Grid Grid newLines = new Grid(); Bmain_Chart.Content = newLines; // 重新创建所有LineGraph并添加到新容器 for (int i = 0; i < 25; i++) { var lg = new LineGraph(); newLines.Children.Add(lg); lg.Stroke = new SolidColorBrush(Color.FromArgb(255, 0, (byte)(i * 10), 0)); lg.Description = String.Format("Data series {0}", i + 1); lg.StrokeThickness = 2; lg.Plot(x, x.Select(v => Math.Sin(v + i / 10.0)).ToArray()); } // 测量、排列并渲染 Bmain_Chart.Measure(new Size(width, height)); Bmain_Chart.Arrange(new Rect(new Size(width, height))); Bmain_Chart.UpdateLayout(); RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); bmp.Render(Bmain_Chart); var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); using (Stream stm = File.Create(@"c:\MyCustomPath\test.png")) { encoder.Save(stm); } }
效果验证
用方案一修改后,导出的图像应该会和原界面显示的图表完全一致,包含所有25条折线系列。
内容的提问来源于stack exchange,提问作者Ericson da Fonseca
相关产品推荐
相关产品推荐

