views:

946

answers:

1

I have a silverlight control that prints to about 1.5 pages. I'd like to try and scale to fit onto a single page.

I'm using the new Printing API in Silverlight 4.

I've modified the docToPrint.PrintPage handler as follows :

    var renderHeight = item.RenderSize.Height;
    var printableHeight = args.PrintableArea.Height;

    var scale = printableHeight / renderHeight;

    item.RenderTransform = new ScaleTransform()
    {
        ScaleX = Math.Min(1, scale),    // dont zoom in
        ScaleY = Math.Min(1, scale)
    };

    item.UpdateLayout();
    args.PageVisual = item;

This just calculates the transform needed to fit to page. In fact the on-screen rendered control shrinks accordingly - but it always prints out full size.

I know Shawn Wildermuth blogged about printing - and some of the comments at least suggest that transforms don't work for printing.

Is there a workaround for this yet? To be frank I don't actually need printing support - but was just adding it as a bonus feature - so I'll just have to split the page at an arbitrary point if i can't figure this out.

+1  A: 

I have got something like that to work ... mine takes all the objects from a particular stackpanel and scales them to a page and then puts them back

Print Class :

  public class PrintReport
 {
    private Grid _visual;
    private StackPanel _panel;
    private FrameworkElement _header;

    private string _pageText = "Page ";
    private string _dateText = "Date ";
    private string _title;
    private string _subTitle;
    public StackPanel pageroot;

    public PrintReport()
    {
        _visual = new Grid();
        _panel = new StackPanel()
        {
            Margin = new Thickness(40),
        };
        PageNumber = 0;
        _visual.Children.Add(_panel);


    }

    public void Print()
    {
        CreateHeader();
        var pd = new PrintDocument();
        pd.DocumentName = this.Title;
        pd.PrintPage += new EventHandler<PrintPageEventArgs>(pd_PrintPage);
        pd.EndPrint += new EventHandler<EndPrintEventArgs>(pd_EndPrint);
        pd.Print();
    }

    void pd_EndPrint(object sender, EndPrintEventArgs e)
    {
        OnEndPrint(e);
    }

    private UIElement currentElement = null;
    private List<UIElement> pastElements = new List<UIElement>();
    private void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        PageNumber++;
        if (currentElement != null)
        {
            _panel.Children.Remove(currentElement);
            pastElements.Add(currentElement);
        }
        currentElement = pageroot.Children.First();
        if (_panel.Children.Count == 0)
        {
            _panel.Children.Add(_header);
        }
        _visual.Height = e.PrintableArea.Height;
        _visual.Width = e.PrintableArea.Width;
        double totalHeight = e.PrintableArea.Height - this.Margin.Top - this.Margin.Bottom;
        double totalWidth = e.PrintableArea.Width - this.Margin.Left - this.Margin.Right;
        double height;
        if (_header.ActualHeight > 0)
        {
            height = _header.ActualHeight;
        }
        else
        {
            _header.Measure(new Size(totalWidth, totalHeight));
            height = _header.DesiredSize.Height;
        }


         var hold = currentElement;
         pageroot.Children.Remove(hold);
          _panel.Children.Add(hold);


        e.PageVisual = _visual;
        e.HasMorePages =  pageroot.Children.Count > 0; 

    }

    private TransferCalcs CalcScaleVar(double objW, double objH, double totalWidth, double printHeight, double TopMargin, double BotMargin, double Header)
    {
        var retVal = new TransferCalcs();
        retVal.scaleX = totalWidth / objW;
        retVal.TranslateX = (objW - totalWidth) / 2;
        retVal.scaleY = (printHeight - TopMargin - BotMargin - Header) / objH;
        return retVal;
    }


    private void CreateHeader()
    {
        var border = new Border()
        {
            BorderThickness = new Thickness(2),
            BorderBrush = new SolidColorBrush(Colors.Black),
            Margin = new Thickness(0, 0, 0, 10),
            CornerRadius = new CornerRadius(3),
        };

        var grid = new Grid();
        grid.ColumnDefinitions.Add(new ColumnDefinition()
        {
            Width = new GridLength(10)
        });
        grid.ColumnDefinitions.Add(new ColumnDefinition()
        {
            Width = new GridLength(1, GridUnitType.Star)
        });
        grid.ColumnDefinitions.Add(new ColumnDefinition()
        {
            Width = new GridLength(0, GridUnitType.Auto)
        });
        grid.ColumnDefinitions.Add(new ColumnDefinition()
        {
            Width = new GridLength(0, GridUnitType.Auto)
        });
        grid.ColumnDefinitions.Add(new ColumnDefinition()
        {
            Width = new GridLength(10)
        });
        grid.RowDefinitions.Add(new RowDefinition()
        {
            Height = new GridLength(0, GridUnitType.Auto)
        });
        grid.RowDefinitions.Add(new RowDefinition()
        {
            Height = new GridLength(0, GridUnitType.Auto)
        });

        // Title
        var tb = new TextBlock()
        {
            FontWeight = FontWeights.Bold,
            FontSize = 14,
        };
        tb.SetBinding(TextBlock.TextProperty, new Binding()
        {
            Path = new PropertyPath("Title"),
            Source = this,
        });
        grid.Children.Add(tb);
        Grid.SetColumn(tb, 1);

        // SubTitle
        tb = new TextBlock();
        tb.SetBinding(TextBlock.TextProperty, new Binding()
        {
            Path = new PropertyPath("SubTitle"),
            Source = this,
        });
        grid.Children.Add(tb);
        Grid.SetColumn(tb, 1);
        Grid.SetRow(tb, 1);

        // PageText
        tb = new TextBlock()
        {
            VerticalAlignment = VerticalAlignment.Center,
        };
        tb.SetBinding(TextBlock.TextProperty, new Binding()
        {
            Path = new PropertyPath("PageText"),
            Source = this,
        });
        grid.Children.Add(tb);
        Grid.SetColumn(tb, 2);

        // DateText
        tb = new TextBlock();
        tb.SetBinding(TextBlock.TextProperty, new Binding()
        {
            Path = new PropertyPath("DateText"),
            Source = this,
        });
        grid.Children.Add(tb);
        Grid.SetColumn(tb, 2);
        Grid.SetRow(tb, 1);

        // PageNumber
        tb = new TextBlock()
        {
            VerticalAlignment = VerticalAlignment.Center,
        };
        tb.SetBinding(TextBlock.TextProperty, new Binding()
        {
            Path = new PropertyPath("PageNumber"),
            Source = this,
        });
        grid.Children.Add(tb);
        Grid.SetColumn(tb, 3);

        // DateValue
        tb = new TextBlock()
        {
            Text = DateTime.Today.ToShortDateString(),
        };
        grid.Children.Add(tb);
        Grid.SetColumn(tb, 3);
        Grid.SetRow(tb, 1);

        border.Child = grid;
        Header = border;
    }
    public event EventHandler<EndPrintEventArgs> EndPrint;

    protected virtual void OnEndPrint(EndPrintEventArgs e)
    {
        if (currentElement != null)
        {
            _panel.Children.Remove(currentElement);
            pastElements.Add(currentElement);
        }
        foreach (var item in pastElements)
        {
            pageroot.Children.Add(item);
        }
        var handler = EndPrint;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public int _pageNumber { get; set; }


    #region PropertyFields
    public FrameworkElement Header
    {
        get { return _header; }
        set { _header = value; }
    }
    public Thickness Margin
    {
        get { return _panel.Margin; }
        set { _panel.Margin = value; }
    }
    public string Title
    {
        get { return _title; }
        set
        {
            if (_title != value)
            {
                _title = value;
                OnPropertyChanged("Title");
            }
        }
    }

    public string SubTitle
    {
        get { return _subTitle; }
        set
        {
            if (_subTitle != value)
            {
                _subTitle = value;
                OnPropertyChanged("SubTitle");
            }
        }
    }

    public string PageText
    {
        get { return _pageText; }
        set
        {
            if (_pageText != value)
            {
                _pageText = value;
                OnPropertyChanged("PageText");
            }
        }
    }

    public string DateText
    {
        get { return _dateText; }
        set
        {
            if (_dateText != value)
            {
                _dateText = value;
                OnPropertyChanged("DateText");
            }
        }
    }

    public int PageNumber
    {
        get { return _pageNumber; }
        set
        {
            if (_pageNumber != value)
            {
                _pageNumber = value;
                OnPropertyChanged("PageNumber");
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

Usage :

private PrintReport printReport;
private void PrintButton_Click(object sender, RoutedEventArgs e)
    {

        printReport = new PrintReport()
        {

            SubTitle = init.PrettyFieldName,
            Title = "Entire Screen Sample" + (DateTime.Now - new DateTime(2009, 12, 23)).TotalMilliseconds,
        }
        printReport.pageroot = pageroot;
        printReport.Print();
    }
Hurricanepkt