如何从Silverlight强制横向打印?

4
使用Silverlight 4,是否可以在横向模式下打印网格并显示所有内容?我们将“页面”构建为Grid,并从PrintDocument的PrintableArea设置转置高度/宽度。 然后,我们应用CompositeTransform来设置旋转和TranslateX。 基本上,它非常类似于此处找到的解决方案
这样可以正确旋转内容,并且所有内容似乎都被拉伸到页面的宽度(在这种情况下是高度),但底部部分被剪切掉了。 它几乎像是内容以正常页面宽度(通常为8.5英寸)显示,尽管它被渲染为页面的高度(11英寸高)。 因此,价值2.5英寸的内容会出现为空白内容,位于页面底部。

注意:我们不是从UI中提取现有的可视元素放入“页面”网格中。我们正在定义DataTemplates并将VM传递给DataContext。就这方面而言,所有内容都被绑定和正确显示,但渲染到打印文档时出了问题。

我们是否遗漏了什么?我们希望避免必须先呈现页面的位图,但如果必须这样做...

更新:根据进一步的调查(并与开始处理报告的团队成员交谈),该代码非常基于Pete Brown的客户端打印。我们对报表进行了分组和增强功能的扩展,但整体布局处理是相同的引擎。

如果您查看Pete Brown的代码,在GetNewPage方法中,我们目前使用的区别如下:

    ...
    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);
    ...

这个自动旋转的功能很好,但是宽度仍然被裁剪,就像渲染页面宽度仍然是纵向一样。即使我已经改变了所有的测量值来进行交换,调用InvalidateMeasure()InvalidateArrangement()也没有改变输出结果。奇怪的是,当我将ScaleX改为大于1时,它会拉伸被裁剪的内容以填充更多的页面。所以似乎父容器在变换之前被裁剪了,尽管代码声明不是这样的。基本上,这似乎是Shawn Wildermuth博客中提到的剪切问题。所以我还在寻找想法/解决方案...
3个回答

2
使用canvas容器控件,并在canvas内部旋转控件。

经过多个小时的纯粹挫败,我最终决定将该控件放在canvas内。哇!!不再被截断了。

请查看以下简单的测试应用程序以进行演示。它只是一个带有打印按钮的页面。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Printing;
using System.Windows.Shapes;

namespace SilverlightApplication1 {

    public partial class MainPage : UserControl {

        public MainPage() {
            InitializeComponent();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e) {
            PrintDocument PD = new PrintDocument();
            PD.PrintPage += PD_PrintPage;
            PD.Print("Print Test");
        }

        void PD_PrintPage(object sender, PrintPageEventArgs e) {

            Canvas OuterCanvas = new Canvas();

            /* a container for everything that will print */
            Border OuterBorder = new Border() {
                BorderThickness = new Thickness(3),
                BorderBrush = new SolidColorBrush(Colors.Red),
                Margin = new Thickness(10)
            };

            double Width = e.PrintableArea.Width - OuterBorder.Margin.Left - OuterBorder.Margin.Right;
            double Height = e.PrintableArea.Height - OuterBorder.Margin.Top - OuterBorder.Margin.Bottom;

            /* NOTE: We're trying to force landscape, so swop the width and height */
            OuterBorder.Width = Height;
            OuterBorder.Height = Width;

            /* on portrait, this line goes down (leave the printer settings, we're trying to force landscape) */
            Line Line = new Line() {
                X1 = OuterBorder.Width / 2,
                Y1 = 0,
                X2 = OuterBorder.Width / 2,
                Y2 = OuterBorder.Height,
                Stroke = new SolidColorBrush(Colors.Blue),
                StrokeThickness = 3
            };

            OuterBorder.Child = Line;

            OuterCanvas.Children.Add(OuterBorder);

            /* rotate 90 degrees, and move into place */
            var transformGroup = new TransformGroup();
            transformGroup.Children.Add(new RotateTransform() { Angle = 90 });
            transformGroup.Children.Add(new TranslateTransform() { X = e.PrintableArea.Width });
            OuterBorder.RenderTransform = transformGroup;

            e.PageVisual = OuterCanvas;

            e.HasMorePages = false;
        }
    }
}

如果您移除外部画布,页面将会显示为被切断的横向打印状态。

1

没有任何基本的Xaml,很难确定问题在哪里。然而,我要猜一下。

您正在使用RenderTransform,但应用变换的元素将向其容器报告原始未转换的尺寸。结果容器会根据这些信息进行剪切。

我建议解决方案是在您的应用程序中包括Silverlight Toolkit,特别是LayoutTransformer控件。将页面内容放置在此控件内。LayoutTransformer将接受您的CompositeTransform并将其放置在其LayoutTransform属性中。区别在于LayoutTransformer应用变换后才报告其尺寸。因此,它的容器不应该对其进行剪切。


我会尝试使用LayoutTransformer,但是我已经在问题中更新了有关报告的信息。不知道这是否会改变您的回答。 - Agent_9191

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接