Printing Support > Advanced Printing |
If you want more control over the printing process, use the GetPageImages method to automatically break up the grid into images that can be rendered onto individual pages. Each image is a 100% accurate representation of a portion of the grid, including styles, custom elements, repeating row and column headers on every page, and so on.
The GetPageImages method also allows callers to scale the images so the entire grid renders in actual size, scales to fit onto a single page, or scales to the width of a single page.
Once you have obtained the page images, you can use the WPF or Silverlight printing support to render them into documents with complete flexibility. For example, you can create documents that contain several grids, charts, and other types of content. You can also customize headers and footers, add letterheads, and so on.
The printing frameworks in WPF and Silverlight are different. The following sections demonstrate how an application can render the C1FlexGrid using the GetPageImages onto a print document in either platform.
Printing documents in WPF requires a slightly different sequence of steps than in Silverlight:
The code below shows a sample implementation of this mechanism.
C# |
Copy Code
|
---|---|
// print the grid void _btnPrint_Click(object sender, RoutedEventArgs e) { var pd = new PrintDialog(); if (pd.ShowDialog().Value) { // get margins, scale mode var margin = 96.0; var scaleMode =; // get page size var pageSize = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight); // create paginator var paginator = new FlexPaginator( _flex, ScaleMode.PageWidth, pageSize, new Thickness(margin), 100); // print the document pd.PrintDocument(paginator, "C1FlexGrid printing example"); } } |
The FlexPaginator class provides the page images and is conceptually similar to the PrintPage event handler used in Silverlight. Implement it as follows:
C# |
Copy Code
|
---|---|
/// <summary> /// DocumentPaginator class used to render C1FlexGrid controls. /// </summary> public class FlexPaginator : DocumentPaginator { Thickness _margin; Size _pageSize; ScaleMode _scaleMode; List<FrameworkElement> _pages; public FlexPaginator(C1FlexGrid flex, ScaleMode scaleMode, Size pageSize, Thickness margin, int maxPages) { // save parameters _margin = margin; _scaleMode = scaleMode; _pageSize = pageSize; // adjust page size for margins before building grid images pageSize.Width -= (margin.Left + margin.Right); pageSize.Height -= (margin.Top + margin.Bottom); // get grid images for each page _pages = flex.GetPageImages(scaleMode, pageSize, maxPages); } |
The constructor creates the page images. They are later rendered onto pages when the printing framework invokes the paginator’s GetPage method:
C# |
Copy Code
|
---|---|
public override DocumentPage GetPage(int pageNumber) { // create page element var pageTemplate = new PageTemplate(); // set margins pageTemplate.SetPageMargin(_margin); // set content pageTemplate.PageContent.Child = _pages[pageNumber]; pageTemplate.PageContent.Stretch = _scaleMode == ScaleMode.ActualSize ? System.Windows.Media.Stretch.None : System.Windows.Media.Stretch.Uniform; // set footer text pageTemplate.FooterRight.Text = string.Format("Page {0} of {1}", pageNumber + 1, _pages.Count); // arrange the elements on the page pageTemplate.Arrange( new Rect(0, 0, _pageSize.Width, _pageSize.Height)); // return new document page return new DocumentPage(pageTemplate); } |
As in the Silverlight example, a helper PageTemplate class is used to hold the grid images and to provide the margins, headers, and footers.
The remaining paginator methods have trivial implementations:
C# |
Copy Code
|
---|---|
public override int PageCount { get { return _pages.Count; } } public override IDocumentPaginatorSource Source { get { return null; } } public override Size PageSize { get { return _pageSize; } set { throw new NotImplementedException(); } } public override bool IsPageCountValid { get { return true; } } } |
The image below shows the document created when the grid is rendered into an XPS file. The image is very accurate, including a custom rating cell used in the sample. Row and column headers are automatically included in every page, as well as a simple page header and the standard “Page n of m” page footers.
Follow these steps to print documents in Silverlight:
The Print method shows a print dialog. If the user clicks OK, the document fires the BeginPrint event once, then PrintPage once for each page, and finally EndPrint when the last page renders. The code below shows a sample implementation of this mechanism.
We use two variables to hold the page images and to keep track of the page being rendered:
C# |
Copy Code
|
---|---|
List<FrameworkElement> _pages;
int _currentPage;
|
Here is the handler called to print the document:
C# |
Copy Code
|
---|---|
// print the grid void _btnPrint_Click(object sender, RoutedEventArgs e) { // create a PrintDocument var pd = new System.Windows.Printing.PrintDocument(); // prepare to print _pages = null; pd.PrintPage += pd_PrintPage; // print the document pd.Print("C1FlexGrid"); } |
The PrintPage method does all of the work. It generates all the page images the first time it is called, then renders the images onto the pages as they are created.
C# |
Copy Code
|
---|---|
void pd_PrintPage(object sender, PrintPageEventArgs e) { if (_pages == null) { // calculate page size, discount margins var sz = e.PrintableArea; sz.Width -= 2 * 96; // one inch left/right margins sz.Height -= 2 * 96; // one inch top/bottom margins // generate the page images _currentPage = 0; _pages = _flex.GetPageImages(ScaleMode.ActualWidth, sz, 100); } // create visual element that represents this page var pageTemplate = new PageTemplate (); // apply margins to the page template pageTemplate.SetPageMargin(new Thickness(_margin)); // add content to page template pageTemplate.PageContent.Child = _pages[_currentPage]; // apply footer text pageTemplate.FooterRight.Text = string.Format("Page {0} of {1}", _currentPage + 1, _pages.Count); // render the page e.PageVisual = pageTemplate; // move on to next page _currentPage++; e.HasMorePages = _currentPage < _pages.Count; } |
Instead of rendering the grid images directly onto the pages, the sample uses a custom auxiliary class called PageTemplate. This class provides the margins, headers, footers, and a ViewBox control that hosts the actual grid images. Rendering the grid images directly onto the page would also work, but the template adds a lot of flexibility. (Note that the PageTemplate class is implanted in the sample and is not part of the C1FlexGrid assembly).
Here is the XAML that defines the PageTemplate class:
XAML |
Copy Code
|
---|---|
<Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="96" /> <RowDefinition Height="*"/> <RowDefinition Height="96" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="96"/> <ColumnDefinition Width="*" /> <ColumnDefinition Width="96"/> </Grid.ColumnDefinitions> <!-- header --> <Border Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="0 12" BorderBrush="Black" BorderThickness="0 0 0 1" > <Grid> <TextBlock Text="ComponentOne FlexGrid" FontWeight="Bold" FontSize="14" VerticalAlignment="Bottom" HorizontalAlignment="Left" /> <TextBlock Text="Printing Demo" FontWeight="Bold" FontSize="14" VerticalAlignment="Bottom" HorizontalAlignment="Right" /> </Grid> </Border> <!-- footer --> <Border Grid.Column="1" Grid.Row="2" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0 12" BorderBrush="Black" BorderThickness="0 1 0 0" > <Grid> <TextBlock x:Name="FooterLeft" Text="Today" VerticalAlignment="Bottom" HorizontalAlignment="Left" /> <TextBlock x:Name="FooterRight" Text="Page {0} of {1}" VerticalAlignment="Bottom" HorizontalAlignment="Right" /> </Grid> </Border> <! -- page content --> <Viewbox x:Name="PageContent" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Left" /></Grid> |