Behaviour-based chart print solution

4 posts, 0 answers
  1. Alex
    Alex avatar
    13 posts
    Member since:
    Jun 2011

    Posted 15 Sep 2011 Link to this post

    Hello.
    In the examples I found the solution that use the RadRichTextBox to print a Chart. As for me, it looks a little strange. So, I use something like this:

    public class ChartPrintBehaviour
    {
        private const double ImageMargin = 100;
        private const double PageMargin = 10;
     
        private readonly RadChart chart;
     
        private readonly string header;
     
        private readonly bool portrait;
     
        public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(ChartPrintBehaviour), new PropertyMetadata(false, IsEnabledChanged));
         
        public static readonly DependencyProperty HeaderProperty = DependencyProperty.RegisterAttached("Header", typeof(string), typeof(ChartPrintBehaviour));
     
        public static readonly DependencyProperty PortraitProperty = DependencyProperty.RegisterAttached("Portrait", typeof(bool), typeof(ChartPrintBehaviour));
     
        public ChartPrintBehaviour(RadChart chart, string header, bool portrait)
        {
            this.chart = chart;
            this.header = header;
            this.portrait = portrait;
        }
     
        public static void SetIsEnabled(DependencyObject dependencyObject, bool isEnabled)
        {
            dependencyObject.SetValue(IsEnabledProperty, isEnabled);
        }
     
        public static bool GetIsEnabled(DependencyObject dependencyObject)
        {
            return (bool)dependencyObject.GetValue(IsEnabledProperty);
        }
     
        public static void SetHeader(DependencyObject dependencyObject, string header)
        {
            dependencyObject.SetValue(HeaderProperty, header);
        }
     
        public static void SetPortrait(DependencyObject dependencyObject, bool portrait)
        {
            dependencyObject.SetValue(PortraitProperty, portrait);
        }
     
        private static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var chart = d as RadChart;
            if (chart == null)
            {
                return;
            }
     
            if (!((bool)e.NewValue))
            {
                return;
            }
            var header = d.GetValue(HeaderProperty);
            var beh = new ChartPrintBehaviour(chart, header == null ? string.Empty : header.ToString(), (bool)d.GetValue(PortraitProperty));
            beh.Attach();
        }
     
        private void Attach()
        {
            chart.CommandBindings.Add(new CommandBinding(ApplicationCommands.Print, PrintExecuted, CanPrintExecute));
        }
     
        private void CanPrintExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = chart != null;
        }
     
        private void PrintExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (chart == null)
            {
                return;
            }
     
            var dlg = new PrintDialog { PrintQueue = LocalPrintServer.GetDefaultPrintQueue() };
            dlg.PrintTicket = dlg.PrintQueue.DefaultPrintTicket;
            if (!portrait)
            {
                dlg.PrintTicket.PageOrientation = PageOrientation.Landscape;
            }
     
            if (!dlg.ShowDialog().GetValueOrDefault())
            {
                return;
            }
     
            var doc = new FlowDocument
            {
                PageWidth = dlg.PrintableAreaWidth - PageMargin,
                PageHeight = dlg.PrintableAreaHeight - PageMargin
            };
     
            FillDocument(doc);
     
            var writer = PrintQueue.CreateXpsDocumentWriter(dlg.PrintQueue);
            writer.Write(((IDocumentPaginatorSource)doc).DocumentPaginator, dlg.PrintTicket);
        }
     
        protected virtual void FillDocument(FlowDocument doc)
        {
            var bi = new BitmapImage();
            bi.BeginInit();
            bi.CacheOption = BitmapCacheOption.OnLoad;
            var ms = new MemoryStream();
            chart.ExportToImage(ms, new PngBitmapEncoder());
            bi.StreamSource = ms;
            bi.EndInit();
             
            var img = new Image
            {
                Source = bi,
                Stretch = Stretch.Uniform,
                Height = doc.PageHeight - ImageMargin,
                Width = doc.PageWidth - ImageMargin,
                VerticalAlignment = VerticalAlignment.Top
            };
     
            Run headerRun = null;
            if (!string.IsNullOrEmpty(header))
            {
                headerRun = new Run(header);
            }
     
            var fig = new Figure
            {
                VerticalAnchor = FigureVerticalAnchor.ContentTop,
                HorizontalAnchor = FigureHorizontalAnchor.ContentCenter
            };
     
            if (headerRun != null)
            {
                fig.Blocks.Add(new Paragraph(headerRun) { TextAlignment = TextAlignment.Center });
            }
     
            var block = new BlockUIContainer(img);
            fig.Blocks.Add(block);
     
            doc.Blocks.Add(new Paragraph(fig));
        }
    }

    After that we can print any Chart with the this code:

      <telerik:RadChart TelerikExtentions:ChartPrintBehaviour.Header="Print Header"
                              TelerikExtentions:ChartPrintBehaviour.IsEnabled="True">
     <telerik:ChartArea.ContextMenu>
          <ContextMenu>
               <MenuItem Header="Print" Command="Print" />
          </ContextMenu>
    </telerik:ChartArea.ContextMenu>
     
  2. Evgenia
    Admin
    Evgenia avatar
    1406 posts

    Posted 21 Sep 2011 Link to this post

    Hi Alex,

    Thanks for sharing your sample code and approach for printing RadChart. I suggest that you send us your sample project so that  as a Code Library sample - it's a place for exchanging code samples, sharing knowledge and getting hands-on experience. For more information you can read here.

    P.S. Your Telerik points were updated.

    All the best,
    Evgenia
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
  3. UI for WPF is Visual Studio 2017 Ready
  4. andrea
    andrea avatar
    1 posts
    Member since:
    Feb 2015

    Posted 10 Nov 2015 Link to this post

    Hello,

     

    i try to use your code but i'm unable to do this:

    <telerik:RadChart TelerikExtentions:ChartPrintBehaviour.Header="Print Header"
                              TelerikExtentions:ChartPrintBehaviour.IsEnabled="True">

     

    What is "TelerikExtensions"​?

     

    thank you

  5. Evgenia
    Admin
    Evgenia avatar
    1406 posts

    Posted 10 Nov 2015 Link to this post

    Hi Andrea,

    TelerikExtensions is a namespace name that points to a local class -- the one that Alex used to create an attached behavior. He posted the full source code below.

    On a side note I'd like to say that we highly encourage our clients to migrate to our newest charting control - RadChartView. It addresses some of the limitations and deficiencies that we have identified in the RadChart implementation over the years (we chose to implement a separate control in order not to break backwards compatibility). Also the RadChartView control has been around for some years and provides rich and mature functionality that covers a large spectrum of user case scenarios. There is a very detailed documentation article that points the differencies between the RadChart and RadChartView controls here.

    Regards,
    Evgenia
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top