How to generate chart image without showing it?

6 posts, 0 answers
  1. Simon
    Simon avatar
    7 posts
    Member since:
    Jul 2011

    Posted 22 Jul 2011 Link to this post

    I would like to generate the charts without actually showing it (in a WPF application), and then save them to image.

    However, when I run, I hit  the InvalidOperationException

  2. Simon
    Simon avatar
    7 posts
    Member since:
    Jul 2011

    Posted 25 Jul 2011 Link to this post

    Got some sample code. I hit 
                        InvalidOperationException: "The calling thread cannot access this object because a different thread owns it."

    at this line:

                         chart.Save(path);

    Please let me know what I can do to avoid this.

    MainWindow.xaml:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Button Content="Save Graph" Height="22" HorizontalAlignment="Left" Margin="423,277,0,0" Name="button1" VerticalAlignment="Top" Width="80" Click="button1_Click" />
        </Grid>
    </Window>


    MainWindow.xaml.cs:

    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Windows;
    using System.Windows.Threading;
    using Telerik.Windows.Controls;
    using Telerik.Windows.Controls.Charting;

    namespace WpfApplication1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, RoutedEventArgs e)
            {
                SaveChartProcessor _ruleProcessor = new SaveChartProcessor();
                _ruleProcessor.SaveImage();
            }
        }

        public class SaveChartProcessor
        {
            public void SaveImage()
            {
                var newThread = new Thread(processChartImageWorker);
                newThread.SetApartmentState(ApartmentState.STA);
                newThread.Start();
            }

            public void processChartImageWorker()
            {
                RadChart chart = GetChart();

                string path = "d:\\newpic.png";

                chart.Dispatcher.Invoke(
                        new Action(() =>
                        {
                            chart.Save(path);
                        }),
                        DispatcherPriority.Normal);
            }

            public RadChart GetChart()
            {
                var chart = new RadChart();
                chart.BeginInit();

                chart.Width = 640;
                chart.Height = 480;
                chart.DefaultView.ChartArea.EnableAnimations = false;

                SeriesMapping sm1 = new SeriesMapping();
                sm1.SeriesDefinition = new LineSeriesDefinition();
                sm1.LegendLabel = "Line Series 1";
                sm1.CollectionIndex = 0;
                ItemMapping im1 = new ItemMapping();
                im1.DataPointMember = DataPointMember.YValue;
                sm1.ItemMappings.Add(im1);
                SeriesMapping sm2 = new SeriesMapping();
                sm2.SeriesDefinition = new LineSeriesDefinition();
                sm2.LegendLabel = "Line Series 2";
                sm2.CollectionIndex = 1;
                ItemMapping im2 = new ItemMapping();
                im2.DataPointMember = DataPointMember.YValue;
                sm2.ItemMappings.Add(im2);

                // Force chart to measure itseft so it provides the actual width and height to export
                chart.Measure(new System.Windows.Size(chart.Width, chart.Height));
                chart.Arrange(new System.Windows.Rect(chart.DesiredSize));

                chart.SeriesMappings.Add(sm1);
                chart.SeriesMappings.Add(sm2);

                chart.EndInit();

                var itemsSource = new List<double>[] { new List<double> { 9, 2, 3, 4 }, new List<double> { 5, 7, 3, 4 } };
                chart.ItemsSource = itemsSource;
                return chart;
            }
        }
    }
  3. UI for WPF is Visual Studio 2017 Ready
  4. Simon
    Simon avatar
    7 posts
    Member since:
    Jul 2011

    Posted 26 Jul 2011 Link to this post

    Why no one reply? Can some one help?
  5. Sia
    Admin
    Sia avatar
    667 posts

    Posted 28 Jul 2011 Link to this post

    Hi Simon,

    First of all, please excuse us for our late reply.
    You can find a possible solution in the attached files. There a RadChart is added to the visual tree but in hidden container. Please let us know whether this is appropriate for your scenario.

    Regards,
    Sia
    the Telerik team

    Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

  6. Simon
    Simon avatar
    7 posts
    Member since:
    Jul 2011

    Posted 28 Jul 2011 Link to this post

    No, I can't do this in my UI thread. In my case, I have to put the logic in a different class that doens't implement WPF window. I need to  spin out a separate thread that calls this class and this class has a function that create the RadChart then save it as image. can you try to modify my codes to see if you can get it working?
  7. Sia
    Admin
    Sia avatar
    667 posts

    Posted 03 Aug 2011 Link to this post

    Hi Simon,

    Please expect soon our answer in the other forum thread concerning the same issue.

    Thank you,
    Sia
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

Back to Top
UI for WPF is Visual Studio 2017 Ready