C#图表与LiveCharts图像 [英] c# chart to image with LiveCharts
问题描述
我有一个小问题.我想将图表导出为图像.我知道使用beto-rodriguez(
i have a little problem. I want to export to an image my charts. I known that is possible with the code given by beto-rodriguez (here).
但是我有一个问题,我无法在屏幕上显示它所拥有的东西.参见上图.在右下角,我将图像保存为png.在图片的左侧,我有一个图表,其中所有参数都显示在我想要的位置.
But i have a problem, i can't have what i could have by displaying it in the screen. See the image above. On the bottom right, i have the image saved in png. And in the left of the image, i have the chart with all the parameters displayed where i want.
您是否知道在保存的图像中是否可能有相同的图表(在左侧)? 实际上,我使用线程来自动捕获(复制/粘贴)图像.
Do you known if it's possible to have the same chart (in the left) in the saved image ? Actually, i use a thread to capture (copy/paste) the image automatically.
您知道我必须设置哪些参数才能获得正确的图像吗?
Do you known what are the parameters i must set on to have the correct image ?
先谢谢了. 问候.
*************************************编辑后
********************************* After edit
对不起,我迟到了.我尝试了您所说的内容,但不幸的是,我无法做到我想要的. 我将解释我的工作: 我有一个"MakeReport"类,可以通过以下方式调用另一个类"GraphMaker":
Sorry for my late repsonse. I try what you said but unfornately I can't made that i want. I will explain what i do: I have a class "MakeReport" who can call another class "GraphMaker" with:
MyGraph = new GraphMaker();
MyGraph = GiveAGraph(MyGraph);
"MakeReport"类将通过子程序"GiveAGraph()"使用一些值来完成图表:
And the class "MakeReport" will complete the chart with some values with the sub-program "GiveAGraph()":
GraphData.SeriesCollection.Add(new RowSeries
{
Title = Criteria,
Values = DataValues,
ScalesYAt = Index,
DataLabels = true
});
"GiveAGRaph()"的结尾.
End of "GiveAGRaph()".
现在我准备好显示一个图表,我想用它制作图像并进行测试(和调试):
Now I have a chart ready to display, i want to use it to make an image and for test (and debug) i show it:
// Chart to Image
MyGraph.GiveMeAnImageFromChart(); <-- to make a picture with the chart
// Show the graph
MyGraph.Show(); <-- for debug and test, i display it.
对于"MyGraph.GiveAnImageFromChart()",我没有与"MyGraph.Show()"相同的结果.图片(另存为png)与显示的图表不同.
With "MyGraph.GiveAnImageFromChart()", i don't have the same result than "MyGraph.Show()". The picture (save as png) is different to the displayed chart.
"GraphMaker"类中包含的子程序"GiveAnImageFromChart"为:
The sub-program "GiveAnImageFromChart" included in the "GraphMaker" class is :
public void GiveMeAnImageFromChart()
{
var viewbox = new Viewbox();
myChart.Background = Brushes.White;
myChart.DataContext = this;
// myChart il faut tout mettre en paramètres
viewbox.Child = myChart;
viewbox.Measure(myChart.RenderSize);
viewbox.Arrange(new Rect(new Point(0, 0), myChart.RenderSize));
myChart.Update(true, true); //force chart redraw
viewbox.UpdateLayout();
SaveToPng(myChart, "chart.png");
//png file was created at the root directory.
}
"myChart"变量是公共的.使用的"SaveToPng"程序来自您的示例(
The "myChart" variable is public. The "SaveToPng" program used come from your example (here).
要保存图片,我尝试使用以下方法:
To save the picture, i try with the following method :
public System.Drawing.Bitmap ControlToImage(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
// render control content
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
Console.WriteLine("Bounds width = " + bounds.Width + " et bounds height = " + bounds.Height);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), bounds.Size));
}
rtb.Render(dv);
//convert image format
MemoryStream stream = new MemoryStream();
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(stream);
return new System.Drawing.Bitmap(stream);
}
使用:
Bitmap ImageChart = MyGraph.ControlToImage(MyGraph, MyGraph.Width, MyGraph.Height);
使用这种方法,我遇到一个错误,因为"bounds.Width"和"bounds.Height"等于-8.最后,我没有任何要转换的图表.
With this method, i have an error because the "bounds.Width" and "bounds.Height" are equal to -8. And finally, i don't have any chart to convert.
我认为我在"ControlImage"中输入了错误的视觉目标",我错过了一些东西,但我不知道该怎么办.如果您需要更多信息,请问我. 预先感谢您的帮助.
I think i give a wrong "visual Target" in the "ControlImage" and I miss something but i don't know what. If you need more information, ask me. Thanks in advance for your help.
PS:对不起,我的英语.不要犹豫,纠正我.
PS: sorry for my english. Don't hesitate to correct me.
推荐答案
感谢bto-rdz,我提出了一个解决方案.我发现我没有正确使用Livecharts. 因此,如果有人需要,我会发布我的代码.
thanks to bto-rdz, i made a solution. I found that i didn't use Livecharts correctly. So i post my code if someone need it.
这是我的GraphMaker.xaml文件:
This is my GraphMaker.xaml file:
<UserControl x:Class="MyProject.GraphMaker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
d:DesignHeight="730" d:DesignWidth="1660">
<Grid>
</Grid>
</UserControl>
还有我的GraphMaker.xaml.cs文件
And my GraphMaker.xaml.cs file
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using LiveCharts;
using LiveCharts.Wpf;
using System.Collections.Generic;
using System.ComponentModel;
namespace MyProject
{
public partial class GraphMaker : UserControl
{
// PUBLIC
public CartesianChart MyTestChart;
public SeriesCollection MySeriesCollection { get; set; }
public string[] Labels { get; set; }
public string AxisTitle { get; set; }
public Func<double, string> YFormatter { get; set; }
public Axis Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, Axis8, Axis9, Axis10, AxisXChart;
public GraphMaker()
{
InitializeComponent();
MySeriesCollection = new SeriesCollection();
MyTestChart = new CartesianChart
{
DisableAnimations = true,
Width = 1600,
Height = 700,
Series = MySeriesCollection
};
MyTestChart.LegendLocation = LegendLocation.Right;
// *** Axis 1 ***
Axis1 = new Axis();
Axis1.Foreground = Brushes.DodgerBlue;
Axis1.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis1.LabelFormatter = YFormatter;
MyTestChart.AxisY.Add(Axis1);
// *** Axis 2 ***
Axis2 = new Axis();
Axis2.Foreground = Brushes.IndianRed;
Axis2.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis2.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis2);
// *** Axis 3 ***
Axis3 = new Axis();
Axis3.Foreground = Brushes.Gold;
Axis3.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis3.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis3);
// *** Axis 4 ***
Axis4 = new Axis();
Axis4.Foreground = Brushes.Gray;
Axis4.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis4.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis4);
// *** Axis 5 ***
Axis5 = new Axis();
Axis5.Foreground = Brushes.DeepSkyBlue;
Axis5.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis5.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis5);
// *** Axis 6 ***
Axis6 = new Axis();
Axis6.Foreground = Brushes.HotPink;
Axis6.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis6.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis6);
// *** Axis 7 ***
Axis7 = new Axis();
Axis7.Foreground = Brushes.Orange;
Axis7.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis7.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis7);
// *** Axis 8 ***
Axis8 = new Axis();
Axis8.Foreground = Brushes.RoyalBlue;
Axis8.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis8.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis8);
// *** Axis 9 ***
Axis9 = new Axis();
Axis9.Foreground = Brushes.Black;
Axis9.Position = AxisPosition.RightTop;
Axis9.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis9);
// *** Axis 10 ***
Axis10 = new Axis();
Axis10.Foreground = Brushes.DarkTurquoise;
Axis10.Position = AxisPosition.RightTop;
YFormatter = value => value.ToString("N2");
Axis10.LabelFormatter = YFormatter;
//MyTestChart.AxisY.Add(Axis10);
AxisXChart = new Axis();
AxisXChart.Title = AxisTitle;
AxisXChart.Labels = Labels;
}
public void TakeTheChart()
{
var viewbox = new Viewbox();
viewbox.Child = MyTestChart;
viewbox.Measure(MyTestChart.RenderSize);
viewbox.Arrange(new Rect(new Point(0, 0), MyTestChart.RenderSize));
MyTestChart.Update(true, true); //force chart redraw
viewbox.UpdateLayout();
SaveToPng(MyTestChart, "Chart.png");
//png file was created at the root directory.
}
public void SaveToPng(FrameworkElement visual, string fileName)
{
var encoder = new PngBitmapEncoder();
EncodeVisual(visual, fileName, encoder);
}
private static void EncodeVisual(FrameworkElement visual, string fileName, BitmapEncoder encoder)
{
var bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(visual);
var frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName)) encoder.Save(stream);
}
}
}
希望能为您提供帮助.
祝您有美好的一天.再见
Have a nice day. Bye.
这篇关于C#图表与LiveCharts图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!