Declined
Last Updated: 29 Jan 2019 12:47 by Maciej
Maciej
Created on: 17 Oct 2018 22:32
Category: ChartView
Type: Feature Request
7
ChartView: Add support for exporting the chart without adding it to the visual tree
Currently, the control relies on its IsLoaded property to determine if it should render its items (axes, data points, annotations, etc.). However, if you measure and arrange the control in code without adding it into the visual tree, the IsLoaded property is not set to True, therefore the chart is not rendered and the image gets empty.

Original description
----------------------------------

Title: RadCartesianChart incorrecly rendered

We're rendering (Telerik) charts in code behind, to include them in a dynamic documentation.

For most controls it works fine - using standard methods (rendering control with System.Windows.Media.Imaging.RenderTargetBitmap and saving the result BitmapSource to disk)

However, it's impossible with RadCartesianChart with CategoricalSeriesDescriptor or ChartSeriesDescriptor. What we are able to get are axes and descriptions, but not bars.

I'm attaching an example - MainWindow displays a chart. I try to also create the chart in code behind. 
In CreateAndSaveChart() method I create a chart with a DataContext, then I call Measure and Arrange methods on it. At this stage the control should be properly initialized and ready to render. (For simplicity I omit rendering control with RenderTargetBitmap - you can preview the control with WPF Tree Visualizer, which will give you the same result). Well, if you preview the control at this stage, you'll see that the chart is missing bars. 
Next I create a new Window with my chart as a content, and display it for a while. Now the chart is fully and correctly rendered. As a workaround we display some Telerik chart in a transparent window to fully render, but such a workaround was reported not to work for some clients and is unacceptable in a long run. With most of Telerik charts we don't have such problems.

Other issue:
- for other Telerik charts we need to wait a few seconds to have it fully rendered. It's be better to have an event informing that the control is ready. 

I'll be happy to add more details if you need any.

* While experimenting with the example I've suddenly managed to render the chart with bars, but this time the rendered size was incorrect (very small)
Attached Files:
6 comments
Maciej
Posted on: 29 Jan 2019 12:47

Sure!

The example project works, and I'll test this code in production soon. Thank you for your kind support!!!

(For future forum users - I've referenced a Theme dll, and I've added styles from it in App.xaml to have example project working. I didn't try referencing NoXaml dlls).

 

Regards,

Maciek Świszczowski

ADMIN
Martin Ivanov
Posted on: 29 Jan 2019 11:17
Hello Maciej,

I will guess that the project references NoXaml dlls on your side. Can you please double check this? If so, merge the required resources are replace the referenced dlls with the Xaml version. 

Read more about Xaml and NoXaml in the help documentation.

See how to merge resources when using NoXaml in the Setting a Theme article.

Regards,
Martin Ivanov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Maciej
Posted on: 29 Jan 2019 10:08

Hi Martin!

Thanks for the answer. That new version looks really promising!

However. when I run it I get an exception:

System.ArgumentNullException
  HResult=0x80004003
  Message=Value cannot be null.
Parameter name: No Canvas found in the control template.
  Source=Telerik.Windows.Controls.Chart
  StackTrace:
   at Telerik.Windows.Controls.ChartView.RadChartBase.OnApplyTemplate()
   at SeriesProvider.MainWindow.PrepareElementForExport(ChartContainer userControl, Size measureSize) in C:\Temp\image-export-updated\MainWindow.xaml.cs:line 48

Telerik controls version: 2018.3.911.45
Tested on a few .NET Framework versions.

 

Regards,

Maciek Świszczowski

 

 

 
ADMIN
Martin Ivanov
Posted on: 28 Jan 2019 14:15
Hello Maciej,

You are correct. The window is not opened on a new thread. I don't remember what happened, but I guess I've missed to add this part in the project. The idea for opening the window on a new thread was based on the approach in the following stackoverflow thread.

However, it turned out that you can export the chart without adding it to the visual tree, but you need to execute some additional steps to do so. Because of this I am adding an example and attaching a new project that shows how to do this. Additionally, I will close this feature request.

Can you please give the project a try and let me know if it helps?

About the rendering event, there is no such thing in the chart because the WPF framework doesn't provide an event that tells you when a UIElement is rendered. You can tell when the control is prepared to be rendered (the Loaded event), but the rendering itself is not exposed. The closest to a rendering event would be scheduling an action via the application dispatcher with DispatcherPriority.ContextIdle, as shown in the following example:
Dispatcher.BeginInvoke(new Action(() => Debug.WriteLine("Rendered.")), DispatcherPriority.ContextIdle, null);
Anyway, this won't do the work if the control is not added to the visual tree.

Regards,
Martin Ivanov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Attached Files:
Maciej
Posted on: 21 Jan 2019 14:35

Hi Martin,

 

Thank you for your replay! And sorry for not replaying to your question for a long time.

I'm afraid you must have attached a wrong version of your solution, as it doesn't contain any code for creating a new UI thread. 
I agree that creating a separate UI thread would be a more elegant solution, but does it fix the issue that I need to wait for a chart to render, and there is no event that informs about the render being done?

Regards,

Maciek Świszczowski

ADMIN
Martin
Posted on: 05 Nov 2018 14:29
Hello Maciej,

Thank you for the detailed information and the project.  

The reported behavior appears because of the nature of the chart's implementation. Basically, when the chart's series provider starts rendering it checks if its IsLoaded property is True and the data is drawn only in this case. However, this is a native WPF property that is set to True only if you add the UIElement in the visual tree. Because the chart is never added in the visual tree the property is never set to True. Therefore, the chart's data is not plotted and the is nothing on the exported picture.

Currently, the only way to export the chart to an image is to add it in the visual tree before this. I am attaching another approach that you can try. Again with a new window, but instead of using async methods, a new UI thread is created for the window with the chart. Can you try also this and let me know how it goes?

We also approved this item.

Regards,
Martin Ivanov
Technical Support Engineer