No trees were harmed in the making of this blog post [How to: Successfully print a Chart with the Silverlight 4 Beta]


This blog has moved to a new location and comments have been disabled.

All old posts, new posts, and comments can be found on The blog of dlaa.me.

See you there!

Comments (22)
  1. SharpGIS says:

    It sounds to me like there’s an obvious piece missing in the Printing API… some way of notifying the print api whether that the control has reached a printable state.

    For instance think of a control that is based on responses from services, and maybe even the responses from the services will again trigger downloading some images etc. So when the control loads, it has to wait for the service to respond and download the images before it can be printed. An obvious solution would be a simple interface that controls could implement to make it easier for them to report to anything trying to print them that they are currently getting ready, and should hold off a second.

    All the printing API has to do is to look for controls in the visual tree that implements this interface, and check their print-state.

  2. Delay says:

    SharpGIS,

    Thanks for the feedback! I actually met with the printing folks to discuss some of the issues I ran into when writing the sample for this post – and we discussed a few different ideas along the lines of what you’re suggesting. However, I’m not sure we discussed your idea specifically. So I’ll pass your comment on to them right now to be sure it’s added to the pool of ideas here. 🙂

    Great suggestion, thank you for sharing it!

  3. SharpGIS says:

    Thanks. It’s specifically an issue we are dealing with, errrr trying to deal with, so an out-of-the-box solution that doesn’t involve ugly hacks like delay timers etc, would be preferable.

  4. KCCE says:

    Print specific visuals via WPF and the toolkit are simply a nightmare. I don’t believe the problem is with the print API.

    One problem is with the design and/or use of the Visual State Manager. The VSM was not designed to handle "Print specific" scenarios.

    Or, if you prefer  to look at the VSM as print agnostic then the various series do not account for a "Print" RevealState. Having to

    retemplate each series is a real pain.

    Second, if XamlReader.Load() is used to obtain the visual and the resulting control is written directly to an xps document the "Loaded"

    event will never be fired (The Legend for a Line series depends on this event). Controls must be rooted to a PresentationSource (like a

    Window) for this event to be raised. The only workaround I’ve found is implementing a PresentationSource (voodoo).

    So, my suggestions for printable charts are:

     1. Add a Print Reveal state.

     2. Don’t force the chart to be rooted in a PresentationSource!

    -Kendall

  5. Delay says:

    Thanks for the feedback, Kendall!

    Adding a custom VSM state for printing is one of the things we discussed internally. But there are two problems with that: 1) doing that alone wouldn’t help unless either the Chart or VSM knew to play to that state in this scenario (and currently there’s no way to know when a control’s being created for printing) and 2) a VSM state for printing is very likely to need to modify some of the same visuals as the VSM state for show/hide, but that’s explicitly not supported by VSM (states may not overlap the things they modify or else problems will result). So while this initially seemed like a good option, we ended up dismissing it for now…

    Regarding your point about PresentationSource, I wonder if you tried the same technique I describe for Silverlight (in this post) on WPF? It seems like it should be just as viable there – and doesn’t require a great deal of additional work. If you’ve tried it and it doesn’t work for you, I’d be interested to hear about your experience.

    Thanks for the help!

  6. codekiwi says:

    How would this method function if I wanted to simply export the charts (contained in a user control) to XPS rather than print, I am having the same issue where I get the chart but no datapoints (kinda makes it data pointless ;P).

    p.s. I’m using the WPF toolkit & MVVM rather than the SL toolkit but as I understand it this shouldn’t affect things.

    Any assistance would be much appreciated.

  7. Delay says:

    codekiwi,

    I’d expect the same concepts I discuss above to apply to that scenario: get things set up, put the root in the visual tree long enough for everything to settle down, then hand it off to some other thing to print/capture/render/output. If you have a specific example of what’s not working, maybe that would help identify the problem?

  8. Michael. says:

    This is a real pain. In as mush as the chart is a cool feature without printing its use is highly limited. Is it not possible to have developed the chart so that by just setting a property to true or false  in the chart, the animation will be enabled or disabled. I noticed a property called animationsequence and  i thought that setting the sequence to simultanous will take the fading in away. nothing happened. The application I am developing is a variable data software that handles thousands of data and generates thousands of XPS paged document using multitreading. How can the chart be added in the visual tree and extracted out again. I am not using the XPS printer driver in vista, I am using Xpsdocumentwriter thus it does not require the user to answer to the print dialog box. I dont mind retemplating the whole datagrid template.  I downloaded the toolkit source code just to play around with it and found the generic.xaml file that defined all the template.  Will removing the VisualStateManager section in the template fix my problem or are there more to retemplating the chart to disable the animation effect. I urgently need answers.

    Regards

  9. Delay says:

    Michael,

    As I note in the post above, re-Templating the DataPoints to remove the VSM group/states RevealStates/Shown/Hidden is a 100% reliable way to avoid this issue.

  10. Michael says:

    Hi Delay, Thanks once more for a speedy response. Ok. I have implemented a resource dictionary which is a copy of the generic.xaml file in the theme folder of the toolkit source file. I have removed all the visualstate group element and also set the opacity of the root elements to 1 instead of 0.  added the resource file in my app.xaml file. that did not help in anyway, the transition still ocurs and the xps file is still faded. Is there anything I need to do to make this work. I have pasted the resource dictionary below. ur assistance is hightly appreciated. The only style I removed is the Chart style. But every other thing is the same as the generic.xaml

    <ResourceDictionary

      xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"

                       xmlns:chartingprimitives="clr-namespace:System.Windows.Controls.DataVisualization.Charting.Primitives;assembly=System.Windows.Controls.DataVisualization.Toolkit"

                       xmlns:datavis="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"

                       xmlns:x="schemas.microsoft.com/…/xaml"

                       xmlns="schemas.microsoft.com/…/presentation">

       <!–  charting:AreaDataPoint  –>

       <!–  charting:AreaSeries  –>

               </Setter.Value>

           </Setter>

           <Setter Property="Template">

               <Setter.Value>

                   <ControlTemplate TargetType="{x:Type charting:AreaSeries}">

                       <Canvas x:Name="PlotArea">

                           <Path Data="{TemplateBinding Geometry}" Fill="{TemplateBinding Background}" Style="{TemplateBinding PathStyle}" />

                       </Canvas>

                   </ControlTemplate>

               </Setter.Value>

           </Setter>

       </Style>

       <!–  charting:AxisLabel  –>

       <!–  charting:BarDataPoint  –>

       <!–  charting:BubbleDataPoint  –>

       <!–  charting:ColumnDataPoint  –>

       <!–  charting:DataPointSeries  –>

       <!–  charting:DateTimeAxisLabel  –>

       <!–  charting:DisplayAxis  –>

               </Setter.Value>

           </Setter>

           <Setter Property="MajorTickMarkStyle">

               <Setter.Value>

               </Setter.Value>

           </Setter>

           <Setter Property="GridLineStyle">

               <Setter.Value>

               </Setter.Value>

           </Setter>

           <Setter Property="Template">

               <Setter.Value>

                   <ControlTemplate TargetType="{x:Type charting:DisplayAxis}">

                       <Grid x:Name="AxisGrid" Background="{TemplateBinding Background}">

                           <datavis:Title x:Name="AxisTitle" Style="{TemplateBinding TitleStyle}" />

                       </Grid>

                   </ControlTemplate>

               </Setter.Value>

           </Setter>

       </Style>

       <!–  charting:LegendItem  –>

       <!–  charting:LineDataPoint  –>

       <!–  charting:LineSeries  –>

               </Setter.Value>

           </Setter>

           <Setter Property="Template">

               <Setter.Value>

                   <ControlTemplate TargetType="charting:LineSeries">

                       <Canvas x:Name="PlotArea">

                           <Polyline Points="{TemplateBinding Points}" Stroke="{TemplateBinding Background}" Style="{TemplateBinding PolylineStyle}" />

                       </Canvas>

                   </ControlTemplate>

               </Setter.Value>

           </Setter>

       </Style>

       <!–  charting:NumericAxisLabel  –>

       <!–  charting:PieDataPoint  –>

       <!–  charting:PieSeries  –>

       <!–  charting:RangeAxis  –>

               </Setter.Value>

           </Setter>

           <Setter Property="MajorTickMarkStyle">

               <Setter.Value>

               </Setter.Value>

           </Setter>

           <Setter Property="MinorTickMarkStyle">

               <Setter.Value>

               </Setter.Value>

           </Setter>

           <Setter Property="GridLineStyle">

               <Setter.Value>

               </Setter.Value>

           </Setter>

           <Setter Property="Template">

               <Setter.Value>

                   <ControlTemplate TargetType="charting:RangeAxis">

                       <Grid x:Name="AxisGrid" Background="{TemplateBinding Background}">

                           <datavis:Title x:Name="AxisTitle" Style="{TemplateBinding TitleStyle}" />

                       </Grid>

                   </ControlTemplate>

               </Setter.Value>

           </Setter>

       </Style>

    </ResourceDictionary>

  11. Micheal says:

    The Copy and pasting did not seem to work as I can see most of the text are not rendered properly. Anyway, I hope you understand my plight.

  12. Delay says:

    Michael,

    That's not how generic.xaml works, unfortunately. What I think you'll find easier is to just specify the relevant DataPoint Style (ex: LineDataPoint for LineSeries) by setting it as the Series.DataPointStyle property for the Series you create. I have some examples of using DataPointStyle here: blogs.msdn.com/…/chart-tweaking-made-easy-how-to-make-four-simple-color-tooltip-changes-with-silverlight-wpf-charting.aspx

  13. Michael says:

    This is just not working for me. I believe there is more to this than just templating the LineDatapoint for the the Line series. I created a LinedataPoint template and applied it to the Lineseries.DataPointStyle.

     LineSeries series = new LineSeries();  

                       series.ItemsSource = TheSetting.TheData[0];

                       series.DependentValuePath = "Value";

                       series.IndependentValuePath = "Key";

                       series.DataPointStyle = (Style)TheChart.FindResource("newLinePoint");        

    newlinePoint is the style I defined in my resources. the style reflected in the application but when I previewed it in the xps viewer. The connecting lines did not show.  Do you have an application that you have done this on that is working for you, I mean applied a style on and was able to print using xpsdocumentwriter.

    below is my linedatapoint style.

  14. Delay says:

    Michael,

    It sounds like the DataPoints are now showing up for you and it's now just the line that's not showing up. I glossed over the details in my post above (because they weren't relevant), but the line of a LineSeries is hooked up a little weirdly. To make a long story short, if you set the Background property of the LineSeries to the Brush you want used for the Line's Stroke (do this at the time the LineSeries is created; right after you set DataPointStyle in your example code above), then the line *should* show up in your scenario. (Assuming I'm remembering everything correctly!)

  15. Michael says:

    Thanks delay. now the lines show in the XPS file. However, my application will be using all the other chart series, piechart Barchart and others. The pie chart datapoints and the bar chart datapoints  fade in when dropped on the canvas. thus when previewed in the XPS file sometimes the chart clarity varies but most times it appears blurry as I believe its because of the 0.5 secons animation interval. How can this isses be fixed.below is my code

    PieSeries pie = new PieSeries();

                       pie.ItemsSource = TheSetting.TheData[0];

                       pie.DependentValuePath = "Value";

                       pie.IndependentValuePath = "Key";                

                       TheChart.Series.Clear();

                       TheChart.Series.Add(pie);                  

                       TheChart.ChartAreaStyle = (Style)TheChart.FindResource("chartareastyle");

                       TheChart.PlotAreaStyle = (Style)TheChart.FindResource("plotAreastyle");

                       pie.StylePalette = ((PieSeries)TheChart.FindResource("PiePalete")).StylePalette;

    for the chartarea style- Setter Property="Background" Value="green" —-this is not refrected in the chart.

    for the plotareastyle – Setter Property="Background" Value="White"——- this reflected.

    the stylepalette was a set of setters for the piedatapoint. The setting reflects but the fade in when droped. hence does not show properly in the XPS file Preview. Your suggestion will be appreciated.

  16. Delay says:

    Michael,

    Every DataPoint default Template includes the RevealStates/Shown/Hidden states for animating the points in and out. You don't specifically indicate that you're providing a custom Template for the PieDataPoint instances that excludes these VSM states, so that's probably the issue. Regarding why ChartAreaStyle isn't having an effect, I'm guessing that the resource isn't being found and FindResource is returning null – perhaps because of a spelling/casing error (for example, the 'A' in plotAreaStyle is capitalized while it's not in "chartareastyle").

    Hope this helps!

  17. Michael says:

    So how do I indicate a template for the datapoint of the PieSeries or that of the Columnseries? I have in my resource file a style for the pie series datapoint

    Style  x:Key="{x:Type charting:PieDataPoint}" TargetType="{x:Type charting:PieDataPoint}"

           Setter Property="Background" Value="Orange"

          Setter Property="BorderBrush" Value="White"

           Setter Property="BorderThickness" Value="1"

           Setter Property="IsTabStop" Value="False"

           Setter Property="RatioStringFormat" Value="{}{0:p2}"

           Setter Property="Template"

             Setter.Value

                   ControlTemplate TargetType="{x:Type charting:PieDataPoint}"

                       Grid x:Name="Root" Opacity="1">

                           Path x:Name="Slice" Data="{TemplateBinding Geometry}" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeMiterLimit="1"

                               ToolTipService.ToolTip

                                   StackPanel

                                      ContentControl Content="{TemplateBinding FormattedDependentValue}"

                                       ContentControl Content="{TemplateBinding FormattedRatio}"

                                   StackPanel

                               ToolTipService.ToolTip

                           Path

                           Path x:Name="SelectionHighlight" Data="{TemplateBinding GeometrySelection}" Fill="Red" StrokeMiterLimit="1" IsHitTestVisible="False" Opacity="0"

                           Path x:Name="MouseOverHighlight" Data="{TemplateBinding GeometryHighlight}" Fill="White" StrokeMiterLimit="1" IsHitTestVisible="False" Opacity="0"

                       Grid

                   ControlTemplate

               Setter.Value

           Sette

       Style

    but even with this style in my app.xaml the fade in still occurs. As you can see there is no VSM in the style. and the key value is set to the piedatapoint type, so I expect all piedatapoint style to use it.  

    for the chartAreaStyle

    The returned style is not null as I applied a break point and it is retrieving the value in the resource file. I actually copied the key from the resource file and pasted in the findresource call.

    I cant believe how difficult it is to get this control to work.

  18. Delay says:

    Michael,

    I don't believe the x:Key="{x:Type}" technique works on Silverlight (or at least it didn't used to) – I cover an approach that works in the following blog post: blogs.msdn.com/…/chart-tweaking-made-easy-how-to-make-four-simple-color-tooltip-changes-with-silverlight-wpf-charting.aspx

    The first step is to be sure your custom PieDataPoint Style is being applied – because if that's not working, then the attempts to disable the RevealStates won't have a chance. 🙂

    Regarding ChartAreaStyle, I've just checked the default Template for Chart and it appears that the Panel to which PlotAreaStyle is applied completely overlaps the one to which ChartAreaStyle is applied. So if you haven't played around with the Margins/Padding, it may well be that ChartAreaStyle is working in your scenario, but is simply obscured by the PlotAreaStyle. (Note that we use ChartAreaStyle to apply sizing constraints, not for its Background.)

  19. Michael says:

    Delay,

    I am not working on Silverlight. I am developing a wpf Application. I understand that I have to apply the PiedataPointstyle. I am not debating that. that was why i wrote this style . Style  x:Key="{x:Type charting:PieDataPoint}" TargetType="{x:Type charting:PieDataPoint}"

    Most of the other series have the DatapointStyleProperty but the PieChart does not have that. So how do I apply the datapointStyle to the piechart. I have resolved the issue for the columnseries

    Everything I have tried so far have failed. Can you please provide me with a litle code snippet on how to apply the datapointstyle to the pieChartdatapoint.

    Thanks for clearing the issue with the ChartareaStyle.

  20. Michael says:

    Hi Delay. Thanks for your Patient I have resolved the templating issues.

    regards Michael

  21. Michael says:

    I have resolved the PieChartdataPointTemplating issue

  22. Delay says:

    Michael,

    Great news, thanks for hanging in there!! 🙂

Comments are closed.