SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, iOS Chart, Android Chart and JavaScript Chart Components
Do you have any examples for printing and screenshots when using a multi-pane chart using a SciChartGroup? Our application uses multi-pane charts and needs to be able to print and create screen captures of these as a single unit.
Hi David,
We don’t have an example for this, but if the chart is already on-screen, it’s quite easy to do. WPF has built-in mechanisms for printing and rendering WPF UIElements to bitmap. For instance, if you have the following code:
<SciChartGroup x:Name="ChartGroup">
... multiple charts defined in here ...
</SciChartGroup>
Then to print it, you simply need to call PrintDialog.PrintVisual on the SciChartGroup
// Printing
var dialog = new PrintDialog();
if (dialog.ShowDialog() == true)
{
dialog.PrintVisual(ChartGroup, "Test");
}
or to export it to bitmap, you simply need to use a WPF RenderTargetBitmap on the parent ChartGroup, like so:
var actualHeight = ChartGroup.ActualHeight;
var actualWidth = ChartGroup.ActualWidth;
var renderTarget = new RenderTargetBitmap((int) actualWidth, (int) actualHeight, 96, 96, PixelFormats.Pbgra32);
renderTarget.Render(element);
// renderTarget is now an instance of BitmapSource which you can save or copy to clipboard
Hope this helps,
Andrew
Thanks Andrew. Your example works well for capturing an image of the chart on-screen, but doesn’t work very well for sending to a printer or XPS file. I was able to get a variation on your printing example working that allows printing at a different size or resolution than what is on the screen using a SciChartGroup.
private void PrintButton_Click(object sender, RoutedEventArgs e)
{
var dialog = new PrintDialog();
if (dialog.ShowDialog() == true)
{
var size = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaWidth * 3 / 4);
var scg = CreateSciChartGroupWithoutShowingIt(size);
// And print. This works particularly well to XPS!
Action printAction = () => dialog.PrintVisual(scg, string.Empty);
Dispatcher.BeginInvoke(printAction);
}
}
Here is the method that creates the off-screen control.
/// <summary>
/// This method demonstrates how we can render to bitmap or print a SciChartGroup which is never shown,
/// e.g. if you wanted to create a report on a server, or wanted to grab a screenshot at a different resolution
/// to the currently shown size of the chart
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
private Visual CreateSciChartGroupWithoutShowingIt(Size size)
{
// Create a fresh ChartView, this contains the ViewModel (declared in XAML) and data
var control = new ChartView();
var scg = control.sciChartGroup;
// We must set a width and height. If you are rendering off screen without showing
// we have to tell the control what size to render
scg.Width = size.Width;
scg.Height = size.Height;
scg.Measure(size);
scg.Arrange(new Rect(size));
scg.UpdateLayout();
var chartSurfaces = FindVisualChildren<SciChartSurface>(scg)
.Where(surface => surface.Name != "PART_ScrollbarChartBackground");
// Doing an export sets up the chart for rendering off screen, including handling all the horrible layout issues
// that occur when a WPF element is created and rendered without showing it.
//
// You must call this before printing, even if you don't intend to use the bitmap.
foreach (var sciChartSurface in chartSurfaces)
{
sciChartSurface.Width = sciChartSurface.ActualWidth;
sciChartSurface.Height = sciChartSurface.ActualHeight;
sciChartSurface.ExportToBitmapSource();
}
return scg;
}
This is the only way I could figure out how to find the SciChartSurface objects:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
Please login first to submit.