Wednesday 30 November 2011

Printing in Silverlight

Example:
To make the code listed in this post easier, I am providing the name of the project and an entity of which I will be printing my report from its data.
Project name: SLPrinting
Entity name: Customer (ID, FirstName, LastName, CompanyName)

step 1
=====
Declare IEnumerable of type our entity and fill it with data.
IEnumerable<Customer> _customersToPrint
Create 'PrintDocument' object and implement its printing events by pasting the following in the PrintButton click event:
        private int _printedItems;
        private IEnumerable<Customer> _customersToPrint;
        private void PrintButton_Click(object sender, RoutedEventArgs e)
        {
            var printDoc = new PrintDocument();
            printDoc.BeginPrint += BeginPrint;
            printDoc.PrintPage += PrintPage;
            printDoc.EndPrint += EndPrint;
            printDoc.Print("CustomersReport");  //Document name in the print queue.
            //this.DialogResult = true;
        }
        private void BeginPrint(object sender, BeginPrintEventArgs e)
        {
            _printedItems = 0;
        }
        private void PrintPage(object sender, PrintPageEventArgs e)
        {
            var _myReport = new myReport();
            e.PageVisual = _myReport;
            _myReport.PreparePage(
                _customersToPrint,
                _printedItems,
                e.PrintableArea
                );
            _printedItems += _myReport.NumberOfCustomers;
            e.HasMorePages = _printedItems < _customersToPrint.Count();
        }
        private void EndPrint(object sener, EndPrintEventArgs e)
        {
            //DialogResult = true;
        }


step 2
=====
In Silverlight project Add new item, choose 'Silverlight UserControl' and name it: 'myReport.xaml'
We will use this added item to design our report using a DataTemplate.
paste the following:
<UserControl x:Class="SLPrintingExample.myReport"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <DataTemplate x:Key="dtCustomersTemplate">
            <StackPanel Margin="10">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=FirstName}" Width="200"/>
                    <TextBlock Text="{Binding Path=LastName}" Width="200"/>
                    <TextBlock Text="{Binding Path=CompanyName}"/>
                </StackPanel>
                <Rectangle Fill="Black" Height="2" />
            </StackPanel>
        </DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="spHeader" Grid.Row="0">
            <TextBlock HorizontalAlignment="Center"
                   TextWrapping="Wrap"
                   Text="My Silverlight Report"
                   VerticalAlignment="Center"
                   FontWeight="Bold" />
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="First name" Width="200" />
                <TextBlock Text="Last name" Width="200"/>
                <TextBlock Text="Company name" />
            </StackPanel>
        </StackPanel>
       
        <TextBlock HorizontalAlignment="Center"
                   TextWrapping="Wrap"
                   Text="Place holder"
                   x:Name="txbReportFooter"
                   VerticalAlignment="Center"
                   Grid.Row="2"/>
        <StackPanel Grid.Row="1"
                    x:Name="spCustomersPanel">
        </StackPanel>
    </Grid>
</UserControl>
The UserControl contains the following:
 Description UI x:Name
==================================
  - DataTemplate:  dtCustomersTemplate (How to display each row)
  - Report header:  spReportHeader 
  - Report footer: txbReportFooter 
  - Report details: spCustomersPanel  (Holds the data rows)

step 3
=====
In myReport.xaml.cs paste the following:
        public int NumberOfCustomers { get; private set; }
        public void PreparePage(IEnumerable<Customer> customers, int startIndex, Size pageSize)
        {
            spCustomersPanel.Children.Clear();
            UpdateLayout();
            foreach (Customer custom in customers.Skip(startIndex))
            {
                var content = new ContentPresenter
                {
                    Content = custom,
                    ContentTemplate = Resources["dtCustomersTemplate"] as DataTemplate
                };
                spCustomersPanel.Children.Add(content);
                UpdateLayout();
                if (DesiredSize.Height >= pageSize.Height)
                {
                    spCustomersPanel.Children.Remove(content);
                    break;
                }
            }
            NumberOfCustomers = spCustomersPanel.Children.Count;
            txbReportFooter.Text = string.Format("Customers {0} to {1} ", startIndex + 1, startIndex + NumberOfCustomers);
            UpdateLayout();
        }

No comments:

Post a Comment