I am working on a tool that automatically generates PDFs to automate the process of generating PDFs where basically only the name changes.
In my App I have my UserControl
centered in a grid, just like it is supposed to look.
In the converted XPS document however, my UserControl
clips to the bottom right corner and no matter what variable I change, it doesn't move.
Since the base code for the XPS conversion was something I just copied from another question here, I don't really know what options I have to change the look of the generated XPS.
What I've already tried:
ViewBoxes
I had, because I suspected they might be the reason. Didn't change anything.UserControl
remains.Width
/Height
of many of the controls. Looks different in the tool, no significant changes in the XPS.printDlg.PrintableAreaWidth
and other variables in the printing method (code further below). Doesn't appear to change anything in the resulting XPS.Grid
or ScrollViewer
instead). No changes either.UserControl
and printing it directly, rather than creating a new instance.Grid
(First Grid below MainWindow
), it just prints my gray box (only the right border of the Listbox
is visible)MainWindow.xaml:
<Window x:Class="TestApp.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestApp.View"
xmlns:vm="clr-namespace:TestApp.ViewModel"
mc:Ignorable="d" d:DataContext="{d:DesignInstance Type=vm:MainWindowViewModel,IsDesignTimeCreatable=False}"
Title="MainWindow" Height="950" Width="1050" FontSize="16">
<Grid AllowDrop="True">
<Grid.RowDefinitions>
<RowDefinition Height="95*"/>
<RowDefinition Height="5*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="85*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<ListBox></ListBox>
</Grid>
<Grid Grid.Column="1" x:Name="grid">
<ScrollViewer>
<local:UserControl1 AllowDrop="True" x:Name="ctrl"/>
</ScrollViewer>
</Grid>
</Grid>
<Grid Grid.Row="1" Background="Gray">
<UniformGrid VerticalAlignment="Stretch" Height="40" Rows="1">
<Button Content="Print" Background="White" Margin="3" MaxWidth="120"
Command="{Binding PrintPdfCommand}" CommandParameter="{Binding ElementName=ctrl}"/>
</UniformGrid>
</Grid>
</Grid>
</Window>
UserControl1.xaml (This is the one I want to print):
<UserControl x:Class="TestApp.View.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid>
<Image Source="/Resources/GrayTestBackground.jpg" Stretch="Fill"/>
<Grid Width="440" Margin="330,170,170,100">
<StackPanel>
<TextBox FontSize="36" FontWeight="SemiBold" Text="ABC" Margin="0,0,0,10"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBox Text="ABC" FontSize="17" FontWeight="DemiBold"/>
<TextBox Text="ABC" />
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</Grid>
</Grid>
</UserControl>
MainWindowViewModel:
public class MainWindowViewModel : NotifyBase
{
public MainWindowViewModel()
{
CreateCommands();
}
#region Commands
public ICommand PrintPdfCommand { get; set; }
public void CreateCommands()
{
PrintPdfCommand = new RelayCommand<FrameworkElement>(ExecutePrintPdf);
}
public void ExecutePrintPdf(FrameworkElement element)
{
UserControl1 control = new UserControl1();
control.DataContext = element.DataContext;
using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
string fileName = System.IO.Path.Combine(dialog.SelectedPath, $"test_{ DateTime.Now.ToString("yyyy-MM-dd-HH-mm")}");
FixedDocument fixedDoc = new FixedDocument();
PageContent pageContent = new PageContent();
FixedPage fixedPage = new FixedPage();
PrintDialog printDlg = new PrintDialog();
Size pageSize = new Size(printDlg.PrintableAreaWidth, printDlg.PrintableAreaHeight - 100);
control.Measure(pageSize);
control.Arrange(new Rect(10, 50, pageSize.Width, pageSize.Height));
fixedPage.Children.Add(control);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);
string tempFilename = fileName + "_temp.xps";
XpsDocument xpsDoc = new XpsDocument(tempFilename, FileAccess.Write);
XpsDocumentWriter xWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
xWriter.Write(fixedDoc.DocumentPaginator);
xpsDoc.Close();
}
}
#endregion Commands
}
What I expect (Screenshot from the tool):
I didn't include RelayCommand
& my NotifyBase
base class, which I guess are some classes every WPF-Programmer has at hand anyways, in order to shorten the length of my question. If you need them feel free to leave a comment.
So basically the FixedPage
was responsible for all my troubles.
It always resized my control to an area larger than the area available from my PrintDialog
.
I was under the impression that it was necessary to print a any UI element, since every solution I found online uses it, but I found out I can simply print my control directly.
I had to resize the control a little before printing, but once I removed the FixedPage
, this was fairly easy.
control.UpdateLayout();
control.Width = PrintableSize.Width;
control.Height = PrintableSize.Height;
string tempFilename = fileName + "_temp.xps";
XpsDocument xpsDoc = new XpsDocument(tempFilename, FileAccess.Write);
XpsDocumentWriter xWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
xWriter.Write(control);
xpsDoc.Close();