Pre loader

Screenshots and Printing for SciChartGroup

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

1
0

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.

  • You must to post comments
0
0

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

  • You must to post comments
0
0

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;
            }
        }
    }
}
  • Andrew Burnett-Thompson
    Hi David, thanks for sharing this GREAT example. I was going to say - offscreen is a little tricky. If you can call ExportToBitmapSource() then internally SciChart does all the hacks necessary to get it to render to bitmap without being shown. You would have to call it on every chart surface in the SciChartGroup (which you have done). Your approach looks great, the only way we could improve on this is if we did the same but hid it inside a method in SciChartGroup itself. Best regards, Andrew
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.

Try SciChart Today

Start a trial and discover why we are the choice
of demanding developers worldwide

Start TrialCase Studies