SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and now iOS Charting & Android Chart Components

Welcome to the SciChart Community Forums!

Please use the forums below to ask questions about SciChart. Take a moment to read our Question asking guidelines on how to ask a good question and our support policy. We also have a tag=SciChart on Stackoverflow.com where you can earn rep for your questions!

Please note: SciChart team will only answer questions from customers with active support subscriptions. Expired support questions will be ignored. If your support status shows incorrectly, contact us and we will be glad to help.

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
    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.