Заставить пейзажную печать из Silverlight? - PullRequest
4 голосов
/ 26 августа 2011

Используя Silverlight 4, возможно ли напечатать сетку в альбомном режиме и показать весь контент? Мы создаем «страницу» как Grid и устанавливаем транспонированную высоту / ширину из PrintableArea в PrintDocument. Затем мы применяем CompositeTransform, чтобы установить Rotation и TranslateX. По сути, это очень похоже на решение , найденное здесь .

При этом содержимое корректно поворачивается, и все отображается растягивающимся по ширине (в данном случае и по высоте) страницы, но нижняя часть обрезается. Это почти как содержимое, отображаемое на нормальной ширине страницы (обычно шириной 8,5 дюйма), хотя оно отображается на высоте страницы (высота 11 дюймов). Таким образом, содержимое в 2,5 "выходит в виде пустого содержимого внизу страницы.

Примечание: Мы не вытаскиваем существующий визуальный элемент из пользовательского интерфейса для помещения в "страничную" сетку. Мы определяем DataTemplates и передаем виртуальные машины в DataContext. Все содержимое привязывается и отображается правильно, насколько это возможно, но рендеринг в печатный документ - это то, что идет не так.

Есть что-то, чего мы упускаем? Мы надеемся, что сначала не нужно отображать растровое изображение страницы, но если это то, что мы должны сделать ...

ОБНОВЛЕНИЕ: Основываясь на дальнейшем расследовании (и разговоре с парнем из команды, которая начала работать над отчетами), код очень сильно основан на Печать Пита Брауна на стороне клиента, Мы немного расширили его для группировки и улучшения функций отчета, но в целом обработка макетов - это тот же механизм.

Если вы посмотрите на код Пита Брауна, мы используем текущую разницу в методе 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, оно растягивает обрезанное содержимое, чтобы заполнить большую часть страницы. Таким образом, почти как родительский контейнер обрезается до преобразования, несмотря на то, что в коде указано иное. В основном это похоже на вырезку, которую Шон Вильдермут написал в блоге о . Поэтому я все еще ищу идеи / решения ...

Ответы [ 3 ]

2 голосов
/ 17 декабря 2012

Используйте 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 голос
/ 26 августа 2011

Трудно быть уверенным, в чем проблема, без какого-либо взгляда на какой-то базовый Xaml.Тем не менее, я собираюсь пойти сюда.

Вы используете RenderTransform, но элемент, к которому применяется преобразование, будет сообщать своему контейнеру исходные не преобразованные измерения.В результате контейнер обрезается на основе этой информации.

Я предлагаю решить проблему, включив в ваше приложение набор инструментов Silverlight, в частности элемент управления LayoutTransformer.Поместите страницу внутри этого элемента управления.LayoutTransformer примет ваше CompositeTransform в свойстве LayoutTransform.Разница в том, что LayoutTransformer отчеты - это измерения после того, как применило преобразование.Следовательно, его контейнер не должен обрезать его.

0 голосов
/ 18 февраля 2012

Я боролся с этой же проблемой, и я нашел ответ. Я рыскал в интернете. Вот ссылка на сообщение на форуме, где я нашел свой ответ - http://forums.silverlight.net/t/237438.aspx/1?how+to+print+landscape+using+SL+print+API+

Автор там действительно парень с ответом. Похоже, секрет заключается в том, чтобы вызывать InvalidateArrange и InvalidateMeasure (ох, и растягивать содержимое) ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...