Using Silverlight 4, is it possible to print a grid in landscape mode and have all the content show up? We’re building out the “page” as a Grid and setting the transposed height/width from the PrintDocument’s PrintableArea. Then we’re applying a CompositeTransform to set the Rotation and TranslateX. Essentially, it’s very similar to the solution found here.
This gets the content to be rotated correctly, and everything appears to be stretched the width (well, height in this case) of the page, but the bottom section is being cut off. It’s almost like the content displayed to the normal width of the page (typically the 8.5″ width) although it was rendered to the height of the page (the 11″ height). So the 2.5″ worth of content is coming out as blank content at the bottom of the page.
Note: We’re not pulling an existing visual element out of the UI to put into the “page” Grid. We’re defining DataTemplates and passing VM’s to the DataContext. All the content is being bound and displayed correctly as far as that goes, but the render to the printed document is what’s going wrong.
Is there something that we’re missing? We’re hoping to avoid having to render a Bitmap of the page first, but if that’s what we have to do…
UPDATE: Based upon further investigation (and talking with the guy on the team that started working on the reporting), the code is very heavily based off Pete Brown’s client side printing. We’ve extended it a bit for grouping and enhancing the features of the Report, but overall the layout handling is the same engine.
If you look at Pete Brown’s code, the current difference we’re using is the following in the GetNewPage method:
...
this.CurrentPageNumber++;
Grid pagePanel = new Grid();
LayoutTransformer layoutTransformer = new LayoutTransformer
{
Content = pagePanel,
Tag = this.CurrentPageNumber
};
if (printableArea.Height > printableArea.Width)
{
// printable area is in Portrait mode.
layoutTransformer.Height = printableArea.Width;
layoutTransformer.Width = printableArea.Height;
var transform = new CompositeTransform
{
Rotation = 90,
TranslateX = printableArea.Width,
ScaleX = 1,
ScaleY = 1
};
layoutTransformer.LayoutTransform = transform;
layoutTransformer.ApplyLayoutTransform();
layoutTransformer.RenderTransform = transform;
}
else
{
// printable area is in Landscape mode
layoutTransformer.Height = printableArea.Height;
layoutTransformer.Width = printableArea.Width;
}
Size pageSize = new Size(layoutTransformer.Width, layoutTransformer.Height);
layoutTransformer.HorizontalAlignment = HorizontalAlignment.Stretch;
layoutTransformer.VerticalAlignment = VerticalAlignment.Stretch;
RowDefinition headerRow = new RowDefinition { Height = GridLength.Auto };
RowDefinition itemsRow = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
RowDefinition footerRow = new RowDefinition { Height = GridLength.Auto };
pagePanel.RowDefinitions.Add(headerRow);
pagePanel.RowDefinitions.Add(itemsRow);
pagePanel.RowDefinitions.Add(footerRow);
...
This works great at automatically rotating the content, but the width is still getting chopped off like it’s rendering the page width still as Portrait. Even though I’ve changed all the measurements to be swapped. It seems like calls to InvalidateMeasure() and InvalidateArrangement() make no difference for changing the output. The odd thing is that when I change the ScaleX to something greater than 1, it will stretch the clipped content to fill more of the page. So it’s almost like the parent container gets clipped prior to the transform, despite the code stating otherwise. Basically it seems like the clipping that Shawn Wildermuth blogged about. So I’m still looking for ideas/solutions…
Its difficult to be sure what the problem is without any sight of some basic Xaml. However I’m going to go for a punt here.
You are using a RenderTransform but the element on which the transform is applied will be reporting to its container the original un-transformed dimensions. As result the container is clipping based on that info.
I suggest the solution is to include the Silverlight Toolkit in your applicaion specifically the
LayoutTransformercontrol. Place the page contant inside this control. TheLayoutTransformerwill then accept yourCompositeTransformin itsLayoutTransformproperty. The difference here is theLayoutTransformerreports is dimensions after it has applied the transform. Hence its container should not clip it.