c# - 如何在 UWP 中的多页上打印
问题描述
我有一个在我的 UWP 项目中运行的打印系统。
为了准备我的打印内容,我使用这个:
(来源: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);
}
这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" />
这sourcePage
<RichTextBlock x:Name="PrintContent">
<!-- Content -->
</RichTextBlock>
我的程序设置方式需要能够在单独的页面上打印 RichTextBox 的每一段。
这可能吗?
解决方案
我需要能够在单独的页面上打印 RichTextBox 的每一段。
如果要在单独的页面上打印 RichTextBox 的每个段落,则需要为每个段落创建多个 PrintPages,然后将 PrintPage 放入 PrintingRoot 和 PrintPages 列表。之后,当您添加预览页面时,您需要迭代 PrintPages 并添加它们。
我进行了以下更改,这是一个完整的示例,您可以下载并检查它。
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);
}
推荐阅读
- flutter - 如何在 showModalBottomSheet 的左侧、右侧和底部显示边距?
- android - 如何使用智能手表检测坠落的人?
- php - 无法在 AJAX 中的多选复选框上动态加载相关复选框
- android - 录制 RTMP 流
- c# - 是否可以自动对标记为 [Ignore] 的属性进行 JSON 序列化
- c# - 重复键值违反 SaveChangesAsync 上的唯一约束
- reactjs - 快照测试会取代“标准”测试吗?
- vue.js - 您如何处理来自 VueJS 的 AWS Cognito newPasswordRequired?
- c# - 使用带有 dotMemory 的 IIS Express 尝试定位内存问题时出现 502.3 错误
- r - 为什么我列表中的所有 ggplots 看起来都一样?