Custom WYSIWYG printing of WPF Scheduler

The Scheduler for WPF includes several default printing styles and includesa sample of printing that enables users to get quick printouts. This default printing and previewing uses C1PrintDocument, and it uses scripts to design each printing style. The printout styles are designed to be printer-friendly and are more basic than the C1Scheduler control itself: they lack color, and if your schedules are fairly busy, the printouts don't show long or overlapping appointments exactly the same as they appear on screen. Some users have said they'd like more flexibility with the control: specifically, WYSIWIG printing.

Download sample source code

This article describes a new sample which shows a shortcut approach to printing your Scheduler via RenderTargetBitmap. Using RenderTargetBitmap allows you to print all Scheduler styles, including TimeLine, and keep appointments layout as on-screen.

WYSIWYG Printing in WPF Scheduler

First, let's make a simple scheduling application with a calendar and buttons for navigation and switching views:

WPF Scheduling applicationWPF Scheduling application

Though this sample is called WYSIWYIG printing, we don't need to print thecontrol exactly as it is shown on the screen. For example, if some view doesn't fit into the visible area and the application shows scrollbars, the printout should show the entire view without scrollbars. Therefore, we can't just copy the application UI to the printer. In such cases, we usually create an additional in-memory control, adjust it a bit, and use it for printing.

WPF Scheduler is more complicated. To avoid memory and performance issues, Scheduler for WPF doesn't perform layout if it's not loaded into the visual tree. So to handle printing, we need an invisible C1Scheduler control placed somewhere in the visual tree. To simplify handling different views and page sizes, we'll place it into hidden Popup:

  <!-- hidden Scheduler in Popup is required in the visual tree to support WYSIWYG printing with pagination and honoring page settings -->  
    <!-- set some properties to prevent functionality we don't need in hidden control and to hide elements we don't need to print -->  
    <c1:C1Scheduler x:Name="printScheduler1" BorderThickness="1" ShowNavigationPanels="False" MaxHeight="10000" MaxWidth="10000">  
        <c1:C1SchedulerSettings FirstVisibleTime="07:00:00" ShowReminderDialog="False"/>  

Now let's look at code that calls System.Windows.Controls.PrintDialog.aspx) and starts printing. In this sample, we'll print the same view and date range that's currently displayed in application.

  private void print_Click(object sender, RoutedEventArgs e)  
  // print the date range currently shown in the C1Scheduler. You might allow end-user to select date range via dialog.  
  var printDialog = new PrintDialog();  
  // setup default printer and page orientation  
  printDialog.PrintQueue = System.Printing.LocalPrintServer.GetDefaultPrintQueue();  
  printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket;  
  if (scheduler1.ViewType == ViewType.Month || scheduler1.ViewType == ViewType.TimeLine)  
  printDialog.PrintTicket.PageOrientation = System.Printing.PageOrientation.Landscape;  
  // show print dialog  
  if (printDialog.ShowDialog() == true)  
  // print via paginator  
  var paginator = new C1SchedulerPaginator(scheduler1, printScheduler1,  
  new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight),  
  new Thickness(40, 60, 40, 60) /* hardcoded margin */  
  if (paginator.PageCount > 0)  
  printDialog.PrintDocument(paginator, "C1Scheduler printing test");  

It's fairly simple to set up the page orientation according to the current view and then call PrintDialog.PrintDocument method.The actual job is performed by the C1SchedulerPaginator class.

Generating Document Pages

The C1SchedulerPaginator is inherited from the System.Windows.Documents.DocumentPaginator.aspx) class. It handles pagination and returns an array of page elements used by the PrintDialog for printing. The C1SchedulerPaginator performs the next actions:

  1. Copies all the settings of the currently displayed C1Scheduler view into the hidden C1Scheduler instance
  2. Hides non-working time and adjusts VisualIntervalScale to get best possible fit
  3. Hides some visual elements such as current time indicator, navigation panels, and highlighted selection,
  4. Performs pagination by changing C1Scheduler.VisibleDates collection and C1Scheduler.CalendarHelper.StartDayTime and C1Scheduler.CalendarHelper.EndDayTime properties,
  5. Clips vertical and horizontal scrollbars so that they are not appear in the printed document
  6. Performs layout using selected paper size
  7. Renders individual pages as images
  8. Adds page number and current date to the page header

You can download the sample to see code comments for more details.

Generated Output

To show you actual printing results I used "Microsoft Print to Pdf" printer. Here's the printed MonthView:

MonthView printed to pdfMonthView printed to pdf

Note that the vertical scrollbar is clipped and navigation panels are hidden. Compare it with a screenshot of the application window above. Now compare runtime DayView UI and the printed version:

DayView on the screenDayView on the screen

DayView printed to pdfDayView printed to pdf

The printed version is resized and adjusted to fit into single page, and the vertical scrollbar is removed.

The most complicated part is TimeLine view. It's horizontal, and individual time slots are wide, so there's no good way to print it all on a single page. In theory, it's possible to zoom before printing, but in this case, the result will be not readable. So, the sample generates the print pages for every single day in TimeLine view:

TimeLine view on the screenTimeLine view on the screen

TimeLine view printed to pdfTimeLine view printed to pdf

Horizontal scrollbar is clipped. Note: if your application shows several days in TimeLine view, they'll all be printed. This sample is not complete and doesn't include any options to select date range or view or to edit page headers. But it should be a good starting point if you need WYSIWYG printing.

Custom WYSIWYG printing of WinForms Scheduler


GrapeCity Developer Tools
comments powered by Disqus