Печать окна WPF на одной странице
Я могу напечатать текущий Window
используя следующий код:
PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog().GetValueOrDefault(false))
{
printDialog.PrintVisual(this, this.Title);
}
Однако если Window
не умещается на страницу, она усекается. Как мне сделать Window
соответствовать странице?
Я думаю, мне нужно сначала сделать графический элемент и проверить, подходит ли эта графика к странице, но я пока ничего не нашел.
1 ответ
Есть одно решение, которое многие люди публикуют как свои собственные. Это можно найти здесь:
http://www.a2zdotnet.com/View.aspx?id=66
Проблема в том, что он изменяет размер вашего интерфейса. Таким образом, эта следующая ссылка берет предыдущее решение и изменяет размер до исходного размера, когда это будет сделано. Это работает, хотя я не могу не думать, что где-то есть более элегантное решение:
http://www.slickthought.net/post/2009/05/26/Visual-Tree-Printing-in-WPF-Applications.aspx
Домен Slickthought.net больше не существует. Wayback Machine на помощь.
<Button Content="Print" Command="{Binding Path=PrintCommand}" CommandParameter="{Binding ElementName=ReportPanel}"></Button>
Здесь следует отметить две важные вещи. Во-первых, я использую команду WPF для запуска процесса печати. Вам не нужно делать это таким образом, но это позволяет мне довольно четко привязать докладчика к пользовательскому интерфейсу. Второе - это CommandParameter. Он передает ссылку на ReportPanel. ReportPanel - это просто элемент управления WPF Grid, который обертывает заголовок TextBlock и список, содержащий фактические диаграммы. Упрощенный XAML это:
<Grid x:Name="ReportPanel" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock />
<ListBox/>
</Grid>
С установленным интерфейсом давайте перейдем к коду. Когда пользователь нажимает кнопку "Печать", выполняется следующая команда WPF:
this.PrintCommand = new SimpleCommand<Grid>
{
CanExecuteDelegate = execute => true,
ExecuteDelegate = grid =>
{
PrintCharts(grid);
}
};
Это довольно простые вещи. SimpleCommand реализует интерфейс ICommand и позволяет мне передавать некоторые лямбда-выражения, определяющие код, который я хочу запустить при запуске этой команды. Очевидно, что магия происходит в вызове PrintCharts (grid). Код, показанный ниже, в основном тот же код, который вы найдете в статье Панкаджа с парой модификаций, выделенных красным.
private void PrintCharts(Grid grid)
{
PrintDialog print = new PrintDialog();
if (print.ShowDialog() == true)
{
PrintCapabilities capabilities = print.PrintQueue.GetPrintCapabilities(print.PrintTicket);
double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / grid.ActualWidth,
capabilities.PageImageableArea.ExtentHeight / grid.ActualHeight);
Transform oldTransform = grid.LayoutTransform;
grid.LayoutTransform = new ScaleTransform(scale, scale);
Size oldSize = new Size(grid.ActualWidth, grid.ActualHeight);
Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
grid.Measure(sz);
((UIElement)grid).Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight),
sz));
print.PrintVisual(grid, "Print Results");
grid.LayoutTransform = oldTransform;
grid.Measure(oldSize);
((UIElement)grid).Arrange(new Rect(new Point(0, 0),
oldSize));
}
}
Хорошо, что это за модификации? Наиболее очевидным является то, что я заменяю использование исходного объекта this (который представлял все окно приложения в исходном коде) на элемент управления Grid, который был передан как часть команды. Таким образом, все измерения и преобразования выполняются с использованием сетки. Другое изменение заключается в том, что я также сохранил исходную трансформацию и размер сетки. Причина в том, что когда вы преобразуете сетку, чтобы она соответствовала печатной странице, это также приводит к изменению фактического пользовательского интерфейса приложения. На вашем экране это выглядит не очень хорошо, поэтому после отправки Grid на принтер я преобразую его обратно в исходное расположение экрана.