10 reasons to consider WPF for your next desktop application - Reason 9. Printing

This is the 9th post in the series 10 reasons to consider WPF for your next desktop application by Josh Twist, this part explores Printing in WPF.

You can view the other reasons in the series below:

Earlier I introduced a series of posts entitled 10 reasons to consider WPF for your next desktop application. If you haven't read the intro yet, better head on back and read it first.

Printing is such an important requirement for most Line-of-Business applications but, as far as I can tell, printing in Windows Forms is still a nightmare. Just as nightmarish as drawing your own controls.

In fact, I've seen a lot of people solve this in their thick client by generating HTML, pumping it into a hidden Internet Explorer window and letting that take care of the printing. I can hear you laughing at the back, but HTML is actually pretty good for basic printing.

If only we had a similarly useful retained-mode graphics engine that used elegant markup and could even support advanced printing requirements...

WPF offers all these features and what's more, printing in WPF is a doddle. Admittedly, in this example I'm going to do the minimum I can to print something from WPF and will avoid the advanced stuff.

Throughout the 10 reasons we've been using Xaml and WPF's other cool features to build some reasonably interesting visuals. But what if we wanted to print out some of this stuff?

I've had a little fun with the Reason 9 ClickOnce Sample and created an application that's a bit more entertaining to play with (but only a bit). If you right-click on the white canvas a little circle will be created. You can then left click on a circle and drag it about.

The reason 9 application

Everytime you add a new circle it will be connected to the last selected circle by a line. I'll explain how that works later, but first the printing.

I told you it was easy:

private void _btnPrint_Click(object sender, RoutedEventArgs e)
{
PrintDialog pdg = new PrintDialog();
if (pdg.ShowDialog().GetValueOrDefault())
{
pdg.PrintVisual(_canvas, "My beautiful creation");
}
}

The reason 9 application

Where '_canvas' is the name of the Canvas element I want to print (including its children). What could be easier? Furthermore, unlike HTML you are totally empowered with full control over pagination, margins and much more.

Top Tip - if you're developing some printing support for your application be sure to use something like Send to OneNote and save yourself some paper.

Admittedly, this is a very simple example and using the more advanced features does push the complexity up quite a bit but printing in WPF is still an attractive feature.

What about these connecting lines then

Have I told you how much I love databinding? Sure, databinding in Xaml is awesome but it can be just as useful in code and that's exactly what I put to use here. The idea is simple, we create a line and databind the position of one end of the line to one ellipse and the other to another ellipse. Here's the code I use:

private void JoinEllipses(Ellipse a, Ellipse b)
{
Line line = new Line() { Stroke = Brushes.Black, StrokeThickness = 1 };

// Bind one end of the line to the new ellipse
line.SetBinding(Line.X1Property, new Binding("(Canvas.Left)") { Source = a });
line.SetBinding(Line.Y1Property, new Binding("(Canvas.Top)") { Source = a });

// and the other end to the old ellipse
line.SetBinding(Line.X2Property, new Binding("(Canvas.Left)") { Source = b });
line.SetBinding(Line.Y2Property, new Binding("(Canvas.Top)") { Source = b });

_canvas.Children.Add(line);
}