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();
        }

Saturday 12 November 2011

Display Child data with Parent from different tables in Silverlight Datagrid

Let us describe the problem, we have two tables:

 ParentTable
  FatherID, FatherName

 ChildTable
  ChildID, ChildName, FatherId

Now in DomainService.cs the GetChildTable() query looks like:

        public IQueryable<ChildTable> GetChildTable()
        {
            return this.ObjectContext.ChildTable;
        }

and when we bind FatherName with ChildName in XAML we don't see FatherName as we expect.

            <sdk:DataGrid  x:Name="dgFamily" AutoGenerateColumns="False">
                <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Header="Child name" Binding="{Binding Path=ChildName}" />
                <sdk:DataGridTextColumn Header="Father name" Binding="{Binding Path=FatherTable.FatherName}" />

This is due to Domain Service does not include the FatherTable with ChildTable in the GetChildTable() query, unless we ask for it.

We have to edit the DomainService.cs file and use the 'Include' in our query as:

        public IQueryable<ChildTable> GetChildTable()
        {
            return this.ObjectContext.ChildTable.Include("FatherTable");
        }

Also, if we look at the Metadata file: DomainService.metadata.cs it will look like:

        internal sealed class ChildTableMetadata
        {
            private ChildTableMetadata()
            {
            }
            public FatherTable FatherTable { get; set; }

We need to update and add the '[Include]' before the FatherTable public property, as:

        internal sealed class ChildTableMetadata
        {
            private ChildTableMetadata()
            {
            }
            [Include]
            public FatherTable FatherTable { get; set; }

Now, test you binding..
It is working

Tuesday 8 November 2011

Adding Page Transition Effect in Silverlight Application

In MSVS2010 Create a new Silverlight Navigation Project.
In Silverlight project, right click MainPage.xaml and select Open in Expression Blend.
In Objects and Timeline tab find (UserControl>LayoutRoot>ContentBorder>ContentFrame)
Right click ContentFrame > Edit Template > Edit a copy.
A Create ControlTemplate Resource box will appear.
Name the Key: CustomTransitioningNavFrame.
In Define In:  Choose Resource dictionary and press New... button.
New Item box will appear, name the new dictionary: CustomControls.xaml and press Ok.
Back to the earlier box, choose our new file CustomControls.xaml and press OK.
Delete the ContentPresenter control.
While Border selected add TransitioningContentPresenter control.
Modify XAML of the TCP control,
 Set Transition= DefaultTransition, Normal, UpTransition and DownTransition.
 Set Content={TemplateBinding Content}.
We are done with the minimum Transition effect. We can add our custom transition effect, but this is not covered in this post.

Thursday 3 November 2011

Make Silverlight application run out of the Browser

To make Silverlight application runs out of the Browser follow:
  • Right click Silverlight application > Properties > Silverlight (tab) > check Enable running application out of the browser.
  • Click on Out-of-Browser Settings... button if you like to change the application settings.
  • Right click Silverlight application > Set as StartUp Project.
  • Right click Silverlight application > Properties > Debug (tab) > Choose Out-of-browser application. [We will have to choose the Web application]