Issue:
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:
- Removing all
ViewBoxes
I had, because I suspected they might be the reason. Didn't change anything. - Removing all other Grid Rows and Columns, so only my
UserControl
remains. - Changing
Width
/Height
of many of the controls. Looks different in the tool, no significant changes in the XPS. - Changing
printDlg.PrintableAreaWidth
and other variables in the printing method (code further below). Doesn't appear to change anything in the resulting XPS. - Trying to print elements that are higher up in the visual tree (like the
Grid
orScrollViewer
instead). No changes either. - Removing the parent of my
UserControl
and printing it directly, rather than creating a new instance. - Even when I try to vonvert the topmost
Grid
(First Grid belowMainWindow
), it just prints my gray box (only the right border of theListbox
is visible)
My Code:
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
}
Screenshots:
What I expect (Screenshot from the tool):
Notes:
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.
CodePudding user response:
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();