I’ve wanted to do a “Silverlight vs Flex” series for quite a while now. Both Silverlight and Flex will reach version 4 during the first quarter of this year, at least, that’s what the roadmaps say. With both reaching version 4, this seems like the perfect time to do a comparison about how to implement certain features. Silverlight has been catching up with Flex, but in Silverlight 4, there are features in Silverlight that are just not possible in Flex (COM interop / Drag and Drop from the desktop), while other features that previously were only possible in Flex, are now also available in Silverlight 4. Whether the implementation of these features in Silverlight is as mature as in Flex is what we are going to find out in this series. We’re going to start with how printing is implemented on both platforms.

 

Printing in Silverlight 4

Central to printing in Silverlight 4 is the PrintDocument class. Printing in Silverlight always has the same steps:

  1. Create a PrintDocument object.
  2. Set the document name on the PrintDocument object.
  3. Attach eventhandlers for the PrintPage event and optionally for the StartPrint and EndPrint events.
  4. In the eventhandler for the PrintPage event, create the visual you want to print and assign it to the RootVisual property of the incoming PrintPageEventArgs object.
  5. Specify whether another page will be printed by assigning the HasMorePages property of the incoming PrintPageEventArgs object true or false.
  6. Repeat step 4 and 5 as long as there are pages to print.

All of these steps are shown in the code behind of a Silverlight application that prints “Hello World” when a button is pressed:

   1: using System;

   2: using System.Windows;

   3: using System.Windows.Controls;

   4: using System.Windows.Printing;

   5:  

   6: namespace HelloPrinter

   7: {

   8:     public partial class MainPage : UserControl

   9:     {

  10:         public MainPage()

  11:         {

  12:             InitializeComponent();

  13:         }

  14:  

  15:         private void button1_Click(object sender, RoutedEventArgs e)

  16:         {

  17:             PrintDocument printDoc = new PrintDocument();

  18:             printDoc.DocumentName = "Hello World from Silverlight";

  19:             printDoc.PrintPage += new EventHandler<PrintPageEventArgs>(printDoc_PrintPage);

  20:             printDoc.Print();

  21:         }

  22:  

  23:         void printDoc_PrintPage(object sender, PrintPageEventArgs e)

  24:         {

  25:             StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal };

  26:             panel.Children.Add(new TextBlock() { Text = "Hello ", FontFamily = new System.Windows.Media.FontFamily("Arial"), FontSize = 12 });

  27:             panel.Children.Add(new TextBlock() { Text = "World", FontFamily = new System.Windows.Media.FontFamily("Arial"), FontSize = 12 });

  28:             e.PageVisual = panel;

  29:             e.HasMorePages = false;

  30:         }

  31:     }

  32: }

Line 15 is the eventhandler that gets called when the button is pressed. What stands out is the fact that the visual you want to print, doesn’t have to be part of the visual tree that Silverlight renders to the screen. Another thing to consider is that Silverlight automatically stretches the RootVisual to the height and width of the page. You can check this size by reading the PrintableArea property of the incoming PrintPageEventArgs object. You can override this behavior by setting the height and width properties of the RootVisual explicitly.

Printing in Flex 4

Printing has been in Flex since the first version. Just like in Silverlight it has a couple of steps to follow, but the programming model is quite different. Printing in Flex is not event driven, this are the steps to take in Flex:

  1. Create a FlexPrintJob object, you can compare this more or less with Silverlight’s PrintDocument class.
  2. Specify with a boolean whether you want to print in vector graphics or in bitmap graphics. Bitmap supports transparency, vector not but prints in higher quality.
  3. Call the FlexPrintJob’s start() method. This will show the print dialog and returns true if the user clicked ok. If the start() method returned true, the printer is now waiting for us to send it some pages.
  4. Create a visual object you like to print.
  5. Add the visual object to the display list.
  6. Add the object to the job using FlexPrintJob’s addObject() method. Every visual object is another page, except when a visual object is larger than one page, Flex automatically detects this and prints the object on multiple pages.
  7. When you’re done adding pages / visual objects, call the send() method of the FlexPrintJob class.
  8. Remove the visual objects you added to the display list just for printing.

All of these steps are shown in the code behind of a Flex application that prints “Hello World” when a button is pressed:

   1: protected function button1_clickHandler(event:MouseEvent):void

   2:             {

   3:                 var job : FlexPrintJob = new FlexPrintJob();

   4:                 job.printAsBitmap = false;

   5:                 if(job.start()) {

   6:                     var group : HGroup = new HGroup();

   7:                     group.height = job.pageHeight;

   8:                     group.width = job.pageWidth;

   9:                     var text : SimpleText = new SimpleText();

  10:                     text.text = "Hello ";

  11:                     text.setStyle("fontFamily", "Arial");

  12:                     text.setStyle("fontSize",12);

  13:                     group.addElement(text);

  14:                     text = new SimpleText();

  15:                     text.setStyle("fontFamily", "Arial");

  16:                     text.setStyle("fontSize",12);

  17:                     text.text = "World";

  18:                     group.addElement(text);

  19:                     

  20:                     addElement(group);

  21:                 

  22:                     job.addObject(group, FlexPrintJobScaleType.NONE);

  23:                     

  24:                     job.send();

  25:                     removeElement(group);

  26:                 }

If you look at the code and my explanation above it you can see that Flex printing requires more steps. This is because of the following differences:

  1. In Flex , you can specify how to print, in bitmap mode or in vector mode.
  2. Flex doesn’t automatically scale the visual object to the page size. You can supply a constant defined in the FlexPrintJobScaleType class to specify how Flex should scale when you call the addObject() method, but “NONE” was the only option that printed anything. To scale the object to the page size I set the width and height of the HGroup to print to the “pageHeight” and “pageWidth” properties of the FlexPrintJob class.
  3. Components in Flex are only printed if they are part of the display list. Don’t worry, in the example above you don’t see the HGroup popping up and disappearing during the print. If you remove the visual object from the display list after printing, nobody will notice.

Conclusion

I think the printing in Flex is somewhat more mature than the printing in Silverlight, I like the option of the higher quality vector printing in Flex and that Flex automatically spreads large visual objects across multiple pages, instead of just cutting them off, like Silverlight does. Also, in Flex there is more support for printing than shown above, for example a lot of components have a prepareToPrint() method, which they can override to make themselves look better when printed, for example, by removing scrollbars (they have no use on paper :)), you can also customize how components print themselves by subclassing the component and overriding this method. Finally, there are components especially designed for printing, a PrintDataGrid for example, which makes sure that only whole rows are printed on each page. What I do like in Silverlight is the whole programming model, it feels more intuitive to me. Just for comparison, below are images showing the quality of the prints when printed to a .XPS file. The Flex printing with Vector graphics clearly has the best quality.

 

Flex printing:image Silverlight printing:image
Flex Vector printing:image  

20 thoughts on “Silverlight 4 vs Flex 4: Printing

  1. Comparing Flex to Silverlight is like comparing apples and oranges. Silverlight is a runtime. There is no such thing as a Flex runtime. Flex is a framework and a toolkit.

    Equivalent comparisons would be:
    - Silverlight vs Flash Player capabilities (runtimes)
    - .Net vs Flex (frameworks)
    - XAML vs MXML (markup languages)
    - C# vs ActionScript (compiler languages)

    I think what you’re really comparing in the above examples is the Silverlight and the Flash Player, since the code you’ve used is not Flex Framework-specific, nor do you compare XAML to MXML.

  2. Hi Joeflash,

    No, I am not comparing apples and oranges, I’m comparing printing in Silverlight with Printing in Flex :). Silverlight is more than a runtime, it has a Base Class Library which you can validly compare with Flex, since this BCL is a framework like Flex, it’s just not a separate download. When people refer to Silverlight they usually mean the runtime including the BCL. Likewise, when people refer to Flex they usually mean Flash with the Flex framework. I could have made the title of my post “Silverlight’s Base Class Library vs Flex” or Silverlight vs Flash with Flex” but that’s such a mouth full and people generally get the idea. Just for your information, there is Flex specific code in my post, namely the FlexPrintJob. Like it’s name suggests, this class is only available in Flex, printing in Flash is done with the PrintJob class….

  3. JoeFlash makes some good points, they are just not really applicable to what you’re demonstrating.

    Yes, I too prefer Flex Printing, if it looks as good as you’ve shown. However, I much prefer Silverlight as a development platform.

    For me, it’s the development platform stupid(btw, that’s the name I answer to when my wife calls).

  4. The graphics of the print output do not appear to be 12 point fonts. Would the Silverlight output look that fuzzy if the graphic had not been enlarged?

  5. The graphic itself hasn’t been stretched or something, all are zoomed 500% in Microsoft XPS viewer, to better tell the differences between them.

  6. Is it possible to set the document name on FlexPrintJob object in Flex?
    What I observe when trying to print to PDF using BullZip PDF printer that document name defaults to Flash.pdf

  7. I’m hoping you can help. I’m involved in a start up in the UK developing software for Africa. Our model is to deliver, easy to use, low cost software via SaaS. We do require some richness in the presentation layer and thus are comparing RIA technologies. As it is Africa, the internet connectivity can be intermittent. Thus we require offline capability, with synchronisation when connectivity resumes.
    I don’t want separate code bases – I’d like 1 code base – making it easier to support and maintain
    I don’t expect we’ll need CPU bound portions
    It can run locally, via a browser
    We have.Net, ajax and flex skills – however we’re intending to be completely open source using JBoss suite and MySQL on the back end.
    It needs to be relatively perfomant – not with low latency like banking systems – but still good enough for everyday use

    Any advice, guidance, suggestions, recommendations, comments would be appreciated! And I’m sure due to the brevity of the note, that there are more questions which will help

    Best regards,

    Conor Maguire

  8. Hi Conor,

    I miss any concrete questions in your comment. Could you contact me using the “contact” link on the right of this blog post with some more information?

  9. Hi Alex,

    Comparing the latest versions of Flex and Silverlight for a SAAS software ( Our app sold over the internet, requires some graphics, must be light enough to be accessed through mobile devices, iPad, iPhone, Android) any suggestions on which way to go?

  10. Hi,

    Well, the demand that it must be accessed through mobile devices makes Flex a good choice, but only together with Flash Player 10.1 which will be released shortly and is especially optimised for mobile devices. Silverlight won’t be accessible on mobile devices in the near future, only Windows Phone 7 which isn’t released yet and the question remains whether it will be a success.

    Note that Flex and Silverlight won’t work on the IPhone and IPad, because of the developer restrictions Apple imposes.

    More info about Flash player 10.1 can be found here:
    http://labs.adobe.com/technologies/flashplayer10/

  11. Flex printing (when ported to an AIR application) allows the developer to specify a specific printer or select specific properties of the printer. Examples would include paper size, margins and even the tray to print from.

    Silverlight does not allow access to printer properties even when compiled to a desktop application.

    It would be very nice if Silverlight did this since we design KIOSK style applications and most of our developers were .net programmers.

  12. Nice post. I really appreciate on what both of you talking about. This will help me in doing business about in printing. Thanks, Your such a brilliant

  13. This could be a feature for Elevated Trust applications. Then again, you can also use a Silverlight / WPF combined code base and create a WPF application for the features you desire, much like you use a combined code base for your Flex / AIR applications.

  14. Thanks Alex !!

    I’m starting with Silverlight now it’s good to know some of the limitations of the printing API.

    cheers from Brazil