01-02-2013 02:51 PM
The graph has a default Margin, which is added to the Width and Height of the control (this is why the original code snippet used LayoutInformation.GetLayoutSlot, which returns the full display size of the control).
If you explicitly assign a value of 0 to the margin of the graph, or include the margin in the size of the bitmap, this should avoid the new clipping issue.
01-03-2013 02:31 AM
Thanks, this solved the problem.
01-23-2013 08:42 AM
Hi, Paul!
Another issue: is it possible to copy data from invisible graph? I use it for reporting and don't want to show these temporary graphs. But currently the only way I found to copy graph image is to make it visible.
01-24-2013 01:39 PM
Hi Eugenem,
How do you want to use this data in a report? Do you insert the image into a text file? I found some examples of other users rendering off-screen, like this one (http://stackoverflow.com/questions/1877115/create-wpf-element-offscreen-and-render-to-bitmap), or rendering a not-visible image to disk (http://stackoverflow.com/questions/5868631/render-a-not-visible-wpf-controls-to-an-bitmap-image)
Regards,
Alexandra
01-24-2013 04:20 PM
Using the technique from the Create WPF element offscreen and render to bitmap question Alex+ra mentioned, you can create a graph outside the visual tree and render it to a bitmap:
// Create graph and populate with data.
var graph = new Graph { Margin = new Thickness( ) };
graph.DataSource = ...;
// Perform layout on graph at desired size.
Rect bounds = new Rect( 0, 0, width, height );
graph.Measure( bounds.Size );
graph.Arrange( bounds );
graph.UpdateLayout( );
After layout has been performed, you can use the original bitmap save snippet to generate the image.
01-28-2013 03:45 AM
strange, I do it like follows:
var graph2 = new Graph();
graph2.Margin = new Thickness(0);
Rect bounds = new Rect(0, 0, 950, 450);
graph2.Measure(bounds.Size);
graph2.Arrange(bounds);
graph2.UpdateLayout();
var renderTarget = new RenderTargetBitmap((int)graph2.ActualWidth, (int)graph2.ActualHeight, 96, 96, PixelFormats.Pbgra32);
renderTarget.Render(graph2);
and graph size is 300x200 instead of 950x450
01-28-2013 09:46 AM
The main difference I see is that I used the width and height of the bounds, rather than ActualWidth and ActualHeight. 300 by 200 is the default size of the graph, so it may be an artifact of measuring outside of the visual tree that ActualWidth and ActualHeight report default values.
01-28-2013 10:44 AM
var renderTarget = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32);
this shows the same graph 300x200
01-28-2013 11:20 AM
Just to ensure we're on the same page, here is the complete image test code I am using:
string path = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.Desktop ), "new.png" );
var g = new Graph { Margin = new Thickness( ) };
GenerateData( g, 11 );
// Render graph at desired display size.
Rect bounds = new Rect( 0, 0, 950, 450 );
g.Measure( bounds.Size );
g.Arrange( bounds );
g.UpdateLayout( );
// Save graph to bitmap.
var rtb = new RenderTargetBitmap( (int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32 );
rtb.Render( g );
// Delete existing test file.
if( File.Exists( path ) )
File.Delete( path );
// Save bitmap to disk.
PngBitmapEncoder png = new PngBitmapEncoder { Frames = { BitmapFrame.Create( rtb ) } };
using( Stream stream = File.Create( path ) )
png.Save( stream );
// Show image and close program.
System.Diagnostics.Process.Start( path );
this.Close( );
On my machine, this correctly generates a 950 by 450 pixel image of a graph with 11 plots of random data using this GenerateData helper method:
private void GenerateData( Graph g, int plotCount ) {
Random r = new Random( );
for( int i = 0; i < plotCount; ++i )
g.Data[i] = Enumerable.Repeat( r, 11 ).Select( _ => i + r.NextDouble( ) ).ToArray( );
}
01-28-2013 11:32 AM
Very strange, it suddenly started to work. Probably some bug at our side, or maybe it wasn't compiling somehow.
Thanks for help!