Exporting Chart as Picture File leads to ArgumentException

Hello,

I have a method, that creates a Chart without showing it anywhere and saving it as picture file.
However, this leads to an ArgumentException: 
System.ArgumentException: Value does not fall within the expected range.
   at Syncfusion.UI.Xaml.Charts.ChartBase.Save(String fileName, StorageFolder folderLocation)
   at System.Threading.WinRTSynchronizationContextBase.Invoker.InvokeCore()

I tested the chart by showing it in an DialogBox instead of exporting and it looked just fine, so it seems the Save-Method is responsible for the error.

You can find my code below:
public async Task ExportChart(int width = 1920, int height = 1080)
        {
            //Create base chart
            var exportChart = new SfChart();
            var foreground = new SolidColorBrush(Color.FromArgb(255, 234, 172, 42));
            exportChart.PrimaryAxis = new DateTimeAxis()
            {
                LabelFormat = "dd/MM - HH:mm",
                Foreground = foreground,
                LabelsIntersectAction = AxisLabelsIntersectAction.Auto
            };
            exportChart.SecondaryAxis = new NumericalAxis()
            {
                RangePadding = NumericalPadding.Round,
                Foreground = foreground,
                Header = new TextBlock() { Foreground = foreground, Text = MarketAsset + "/" + BaseAsset }
            };

            //Get Technical Indicator Charts
            NumericalAxis yAxis = new NumericalAxis()
            {
                Header = "Indicators",
                Foreground = foreground,
                OpposedPosition = true
            };
            List> seriesList = new List>();
            foreach (IndicatorLineCollection ilc in IndicatorLines)
            {
                seriesList.Add(await ilc.RenderIndicatorLines(yAxis));     //this method generates some FastLineSeries-Charts which get added to the main chart below.
            }

            //Create Static Candles Chart and add TIs
            var chartCollection = new ChartSeriesCollection();
            var candleChart = new FastCandleBitmapSeries()
            {
                Label = "Candles",
                Foreground = foreground,
                ItemsSource = Candles,
                BearFillColor = new SolidColorBrush(Color.FromArgb(255, 203, 25, 25)),
                BullFillColor = new SolidColorBrush(Colors.Green),
                XBindingPath = "Date",
                Open = "Open",
                High = "High",
                Low = "Low",
                Close = "Close"
            };
            chartCollection.Add(candleChart);
            foreach (List seriesCollection in seriesList)
            {
                foreach (FastLineSeries series in seriesCollection)
                {
                    chartCollection.Add(series);
                }
            }
            exportChart.Series = chartCollection;

            exportChart.Measure(new Size(width, height));
            exportChart.Arrange(new Rect(0, 0, width, height));
            exportChart.GetType().GetMethod("RenderSeries", BindingFlags.NonPublic |
               BindingFlags.Instance).Invoke(exportChart, null);
            exportChart.UpdateLayout();

            //Save PNG
            StorageFile storageFile = await ApplicationData.Current.LocalCacheFolder.CreateFileAsync("ExportedChart.png", CreationCollisionOption.ReplaceExisting);
            Guid encoder = BitmapEncoder.PngEncoderId;
            exportChart.Save(await storageFile.OpenAsync(FileAccessMode.ReadWrite), encoder);
        }


Greetings
Alexander


3 Replies

DD Devakumar Dhanapoosanam Syncfusion Team March 3, 2020 12:08 PM UTC

 
Greetings from Syncfusion. 
 
We would like to let you know that we don’t have support to Save the chart image in UWP without adding it to any Hierarchy. This is a FrameWork level limitation. Since we have used the RenderTargetBitmap to Save chart. 
 
Please refer the below link for more details 
 
Please let us know if you need any further assistance. 
 
Regards, 
Devakumar D 



AL Alexander April 26, 2020 03:44 PM UTC

Hello,

I have found a solution, if anyone ever stumbles across this problem:
Though it does show the chart for a few miliseconds, however this is fully acceptable for my usecase..

public async Task ExportChart(int width = 1920, int height = 1080)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, async () =>
            {
                try
                {
                    //Create app window
                    var appWindow = await AppWindow.TryCreateAsync();
                    appWindow.RequestMoveAdjacentToCurrentView();
                    appWindow.RequestSize(new Size(width, height));
                    appWindow.Title = "Export Chart";

                    //Create your chart here
var exportChart = new SfChart();
(......)

                    exportChart.Measure(new Size(width, height));
                    exportChart.Arrange(new Rect(0, 0, width, height));
                    exportChart.GetType().GetMethod("RenderSeries", BindingFlags.NonPublic |
                       BindingFlags.Instance).Invoke(exportChart, null);
                    exportChart.UpdateLayout();

                    //Fill AppWindow
                    Frame appWindowContentFrame = new Frame();
                    ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
                    var windowGrid = new Grid();
                    windowGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Star) });
                    windowGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1.0, GridUnitType.Star) });
                    windowGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
                    windowGrid.VerticalAlignment = VerticalAlignment.Stretch;
                    //Move chart to appWindow
                    appWindowContentFrame.Content = new Page() { Content = windowGrid };
                    windowGrid.Children.Add(exportChart);
                    await appWindow.TryShowAsync();
                    //Save PNG
                    StorageFile storageFile = await ApplicationData.Current.LocalCacheFolder.CreateFileAsync("ExportedChart.png", CreationCollisionOption.ReplaceExisting);
                    Guid encoder = BitmapEncoder.PngEncoderId;
                    exportChart.Save(await storageFile.OpenAsync(FileAccessMode.ReadWrite), encoder);
                    //Close AppWindow
                    await appWindow.CloseAsync();
                }
                catch (Exception)
                {
//You can add exception handling here, if you want
                }
            });
        }

Greetings
Alexander


SJ Suyamburaja Jayakumar Syncfusion Team April 27, 2020 06:50 AM UTC

Hi Alexander,  
  
We are glad to hear that your requirement has been achieved.  
  
Please let us know if you need any further assistance on this.  
  
Regards,  
Suyamburaja J.  


Loader.
Up arrow icon