Home > Back-end >  Center a Control when converting to XPS
Center a Control when converting to XPS

Time:08-17

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 or ScrollViewer 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 below MainWindow), it just prints my gray box (only the right border of the Listbox 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): Screenshot from the tool

What I get:
Screenshot from the XPS Document

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();
  • Related