Reputation: 181
I have a printing system that functions in my UWP project.
To prepare my print content I use this:
(Sourced from: https://blogs.u2u.be/diederik/post/Printing-from-MVVM-XAML-Windows-8-Store-apps)
public void RegisterForPrinting(Page sourcePage, Type printPageType, object viewModel)
{
this.callingPage = sourcePage;
if (PrintingRoot == null)
{
this.OnStatusChanged(new PrintServiceEventArgs("The calling page has no PrintingRoot Canvas."));
return;
}
this.printPageType = printPageType;
this.DataContext = viewModel;
// Prep the content
this.PreparePrintContent();
// Create the PrintDocument.
printDocument = new PrintDocument();
// Save the DocumentSource.
printDocumentSource = printDocument.DocumentSource;
// Add an event handler which creates preview pages.
printDocument.Paginate += PrintDocument_Paginate;
// Add an event handler which provides a specified preview page.
printDocument.GetPreviewPage += PrintDocument_GetPrintPreviewPage;
// Add an event handler which provides all final print pages.
printDocument.AddPages += PrintDocument_AddPages;
// Create a PrintManager and add a handler for printing initialization.
PrintManager printMan = PrintManager.GetForCurrentView();
try
{
printMan.PrintTaskRequested += PrintManager_PrintTaskRequested;
this.OnStatusChanged(new PrintServiceEventArgs("Registered successfully."));
}
catch (InvalidOperationException)
{
// Probably already registered.
this.OnStatusChanged(new PrintServiceEventArgs("You were already registered."));
}
}
private void PreparePrintContent()
{
// Create and populate print page.
var printPage = Activator.CreateInstance(this.printPageType) as Page;
printPage.DataContext = this.DataContext;
// Create print template page and fill invisible textblock with empty paragraph.
// This pushes all real content into the overflow.
firstPage = new PrintPage();
firstPage.AddContent(new Paragraph());
// Move content from print page to print template - paragraph by paragraph.
var printPageRtb = printPage.Content as RichTextBlock;
while (printPageRtb.Blocks.Count > 0)
{
var paragraph = printPageRtb.Blocks.First() as Paragraph;
printPageRtb.Blocks.Remove(paragraph);
var container = paragraph.Inlines[0] as InlineUIContainer;
if (container != null)
{
// Place the paragraph in a new textblock, and measure it.
var measureRtb = new RichTextBlock();
measureRtb.Blocks.Add(paragraph);
PrintingRoot.Children.Clear();
PrintingRoot.Children.Add(measureRtb);
PrintingRoot.InvalidateMeasure();
PrintingRoot.UpdateLayout();
measureRtb.Blocks.Remove(paragraph);
// Apply line height to trigger overflow.
paragraph.LineHeight = measureRtb.ActualHeight;
}
firstPage.AddContent(paragraph);
};
// Send it to the printing root.
PrintingRoot.Children.Clear();
PrintingRoot.Children.Add(firstPage);
}
The PrintPage
public sealed partial class PrintPage : Page
{
public PrintPage()
{
this.InitializeComponent();
}
public PrintPage(RichTextBlockOverflow textLinkContainer)
: this()
{
textLinkContainer.OverflowContentTarget = continuationPageLinkedContainer;
}
internal void AddContent(Paragraph block)
{
this.textContent.Blocks.Add(block);
}
}
<RichTextBlock x:Name="textContent"
Grid.Row="1"
Grid.ColumnSpan="2"
FontSize="18"
OverflowContentTarget="{Binding ElementName=continuationPageLinkedContainer}"
IsTextSelectionEnabled="True"
TextAlignment="Left"
FontFamily="Segoe UI"
VerticalAlignment="Top"
HorizontalAlignment="Left">
</RichTextBlock>
<RichTextBlockOverflow x:Name="continuationPageLinkedContainer" Grid.Row="2" />
The sourcePage
<RichTextBlock x:Name="PrintContent">
<!-- Content -->
</RichTextBlock>
The way I have my program setup I need to be able to print each paragraph of the RichTextBox on separate pages.
Is this possible?
Upvotes: 0
Views: 617
Reputation: 5868
I need to be able to print each paragraph of the RichTextBox on separate pages.
If you want to print each paragraph of the RichTextBox on separate page, you need to create mutiple PrintPages for each paragraph, then put the PrintPage to the PrintingRoot and a list of PrintPages. After that, when you add the preview pages, you need to iterate PrintPages and add them.
I made the following changes and here is a complete sample, you can download and check it.
private void PreparePrintContent()
{
PrintingRoot.Children.Clear();
// Create and populate print page.
var printPage = Activator.CreateInstance(this.printPageType) as Page;
printPage.DataContext = this.DataContext;
var printPageRtb = printPage.Content as RichTextBlock;
while (printPageRtb.Blocks.Count > 0)
{
PrintPage firstPage = new PrintPage();
firstPage.AddContent(new Paragraph());
var paragraph = printPageRtb.Blocks.First() as Paragraph;
printPageRtb.Blocks.Remove(paragraph);
firstPage.AddContent(paragraph);
NeedToPrintPages.Add(firstPage);
PrintingRoot.Children.Add(firstPage);
};
}
private RichTextBlockOverflow AddOnePrintPreviewPage(RichTextBlockOverflow lastRTBOAdded, PrintPageDescription printPageDescription,int index)
{
......
if (lastRTBOAdded == null)
{
// If this is the first page add the specific scenario content
page = NeedToPrintPages[index];
}
......
}
private void PrintDocument_Paginate(object sender, PaginateEventArgs e)
{
// Clear the cache of preview pages
printPreviewPages.Clear();
this.pageNumber = 0;
// Clear the printing root of preview pages
PrintingRoot.Children.Clear();
for (int i = 0; i < NeedToPrintPages.Count; i++) {
// This variable keeps track of the last RichTextBlockOverflow element that was added to a page which will be printed
RichTextBlockOverflow lastRTBOOnPage;
// Get the PrintTaskOptions
PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);
// Get the page description to deterimine how big the page is
PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);
// We know there is at least one page to be printed. passing null as the first parameter to
// AddOnePrintPreviewPage tells the function to add the first page.
lastRTBOOnPage = AddOnePrintPreviewPage(null, pageDescription,i);
// We know there are more pages to be added as long as the last RichTextBoxOverflow added to a print preview
// page has extra content
while (lastRTBOOnPage.HasOverflowContent && lastRTBOOnPage.Visibility == Windows.UI.Xaml.Visibility.Visible)
{
lastRTBOOnPage = AddOnePrintPreviewPage(lastRTBOOnPage, pageDescription,i);
}
}
PrintDocument printDoc = (PrintDocument)sender;
// Report the number of preview pages created
printDoc.SetPreviewPageCount(printPreviewPages.Count, PreviewPageCountType.Intermediate);
}
Upvotes: 1