1

So I am building a WPF drag and drop designer.

Once the user is done designing I want them to be able to print what they have.

This was working until I decided that all the items on my canvas should actually be databound to the view model. To do this I wrapped my canvas in a Items Control. The problem I am running into now is the print function I built can't access the canvas to print it. I am open to suggestions.

<ItemsControl x:Name="CanvasItemsControl" Grid.Column="1" Width="600" Height="800"  ItemsSource="{Binding CanvasElements}">
    <ItemsControl.ItemsPanel>
       <ItemsPanelTemplate>
           <Canvas Grid.Column="1" AllowDrop="True" Width="600" Height="800" 
                  x:Name="CanvasControl"                
                  Background="White"  
                  DragEnter="CanvasFlowDocument_DragEnter" 
                  DragLeave="CanvasFlowDocument_DragLeave" 
                  DragOver="CanvasFlowDocument_DragOver" 
                  Drop="CanvasFlowDocument_Drop"/>
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
   <ItemsControl.ItemTemplate>
           <DataTemplate>
              <controls:CanvasElement />
           </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

C#

 private void PrintCanvas()
 {

   PrintDialog pd = new PrintDialog();

   if (pd.ShowDialog() == true)
   {

     /*

      NEED TO ACCESS CANVAS CONTROL HERE TO PRINT

      I KNOW THE BELOW PRINT METHOD WORKS. 

      IT WORKED UNTIL I ADDED THE ITEMS CONTROL WRAPPER AROUND THE CANVAS                

     */


      //get the size of the printer page 
      PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket);

      double pageMargin = Math.Min(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight);

      double additionalMargin = Math.Max(0, 20 - pageMargin);
      Size pageSize = new Size(capabilities.PageImageableArea.ExtentWidth - additionalMargin * 2, capabilities.PageImageableArea.ExtentHeight - additionalMargin * 2);

      //get scale of the print wrt to screen of WPF visual 
      double scale = Math.Min(pageSize.Width / CanvasControl.ActualWidth, pageSize.Height / CanvasControl.ActualHeight);
      Size printSize = new Size(CanvasControl.ActualWidth * scale, CanvasControl.ActualHeight * scale);

      Point upperLeft = new Point(capabilities.PageImageableArea.OriginWidth + additionalMargin, capabilities.PageImageableArea.OriginHeight + additionalMargin);

      //Transform the Visual to scale 
      CanvasControl.LayoutTransform = new ScaleTransform(scale, scale);
      CanvasControl.Measure(printSize);
      CanvasControl.Arrange(new Rect(upperLeft, printSize));


      FlowDocument CanvasFlowDocument = new FlowDocument();
      BlockUIContainer buiCont = new BlockUIContainer();


      CanvasControl.Drop -= CanvasFlowDocument_Drop;
      CanvasControl.DragOver -= CanvasFlowDocument_DragOver;
      CanvasControl.DragLeave -= CanvasFlowDocument_DragLeave;
      CanvasControl.DragLeave -= CanvasFlowDocument_DragEnter;


      Grid parent = (Grid)CanvasControl.Parent;

      parent.Children.Remove(CanvasControl);

      buiCont.Child = CanvasControl;
      CanvasFlowDocument.Blocks.Add(buiCont);

      pd.PrintDocument((CanvasFlowDocument as IDocumentPaginatorSource).DocumentPaginator, "Template");

      CanvasFlowDocument.Blocks.Clear();
      buiCont.Child = null;

      ReloadUI(parent);
   }
}
DotNetRussell
  • 9,716
  • 10
  • 56
  • 111

1 Answers1

1

You should be able to use PrintDialog.PrintVisual(Visual,string) to print out your control directly. You may need to play with size though, but the code you have to do the resizing should work. See this post which is similar and links to this article as a possible solution.

Community
  • 1
  • 1
miko
  • 318
  • 2
  • 4