C# 如何在WPF中向FlowDocument添加页脚?

C# 如何在WPF中向FlowDocument添加页脚?,c#,wpf,flowdocument,C#,Wpf,Flowdocument,我的应用程序中有一个流程文档,如下所示: <FlowDocumentScrollViewer Grid.Row="1"> <FlowDocument> <Section> <Paragraph>Header</Paragraph> </Section> <Section

我的应用程序中有一个
流程文档
,如下所示:

   <FlowDocumentScrollViewer Grid.Row="1">
        <FlowDocument>
              <Section>
                    <Paragraph>Header</Paragraph>
               </Section>

               <Section>
                  <Paragraph >
                        Footer
                   </Paragraph>
               </Section>
        </FlowDocument>
   </FlowDocumentScrollViewer>

标题
页脚
我想要的是将第一个
设置为保留在文档顶部作为页眉,将第二个设置为保留在文档底部作为页脚


谁能告诉我最好的方法吗?

你可以试试这个。。希望这有帮助

<Section Name="MainBody" SectionExtensions.ResetPageNumbers="True">
    <!-- Add the document title to the header -->
    <SectionExtensions.HeaderTemplate>
        <DataTemplate>
            <Border BorderBrush="Black" BorderThickness="0,0,0,1">
                <TextBlock Text="Document title" FontSize="16" />
            </Border>
        </DataTemplate>
    </SectionExtensions.HeaderTemplate>


    <!-- Add the page count to the footer -->
    <SectionExtensions.FooterTemplate>
        <DataTemplate>
            <Border BorderBrush="Black" BorderThickness="0,1,0,0">
                <TextBlock Text="{Binding}" FontSize="16" />
            </Border>
        </DataTemplate>
    </SectionExtensions.FooterTemplate>
    <Paragraph>
    ...
    </Paragraph>
</Section>

...

起点是一篇博客文章,其中显示了。其局限性在于,它旨在直接与打印API一起使用。它不能直接用于查看器,因为查看器要求其文档为
FlowDocument
,并且不可能在子类中重写
DocumentPaginator

我为
FlowDocumentPageViewer
找到的解决方案有几个部分。我还没有尝试将其改编为
FlowDocumentScrollViewer
,但使用相同的原则可能是可行的

自定义XAML模板 我首先使用Blend提取
FlowDocumentPageViewer
的默认XAML模板。实际上我还是想删除一些位,但是页眉/页脚的关键更改是(作为统一的差异)

-
+    

您应该能够了解如何覆盖
OnPrintCommand
以将
CustomDocumentPaginator
发送到
XpsDocumentWriter
而不是
((IDocumentPaginatorSource)文档)。DocumentPaginator

包装文档分页器 我说的起点是一篇博客文章,它展示了如何包装
DocumentPaginator
。有一些微妙之处它没有提到,可能是因为它打算打印一次文档,所以作者没有遇到它们

  • DocumentPage
    是一次性的。当您从包装的分页器中获得一页时,您有责任处理它。如果您不这样做,您可能会发现,当您来回导航时,您会得到随机的
    参数异常:在将包装页的
    Visual
    添加到
    ContainerVisual
    时,指定的Visual已经是另一个Visual的子项或合成目标的根
  • 另一种获取
    ArgumentException
    的方法是,当您已经有一个页面的包装副本时,尝试包装页面。例如,如果您打印,可能会发生这种情况,因为
    XpsDocumentWriter
    将请求当前呈现到屏幕上的页面的副本
  • 因此,您需要仔细管理页面的生命周期。我的paginator包装的修改版本是

    类DocumentPaginatorWrapper:DocumentPaginator
    {
    私有厚度(u边);;
    私人文件发布者(Paginator);;
    //需要避免打印时出现“ArgumentException:指定的Visual已是另一个Visual的子级或CompositionTarget的根”的情况
    私有IDictionary_PageCache=新字典();
    公共文档分页器包装(文档分页器分页器,厚度边距)
    {
    _保证金=保证金;
    _Paginator=Paginator;
    this.PageSize=paginator.PageSize;
    //事件
    paginator.ComputePageCountCompleted+=(s,ev)=>此.onComputerPageCountCompleted(ev);
    paginator.GetPageCompleted+=(s,ev)=>this.OnGetPageCompleted(ev);
    paginator.PagesChanged+=(s,ev)=>此.OnPagesChanged(ev);
    }
    公共覆盖文档页面GetPage(内部页码)
    {
    文档页面缓存页面;
    if(_PageCache.TryGetValue(pageNumber,out cachedPage)&&cachedPage.Visual!=null)返回cachedPage;
    DocumentPage page=_Paginator.GetPage(页码);
    //为转换创建可视包装并添加额外内容
    ContainerVisual newpage=新ContainerVisual();
    //要转换包装的页面,请添加页眉和页脚。
    //这是非常特殊的。
    ...
    //注意:我们假设page.BleedBox的X=0,Y=0,Size=page.PageSize
    cachedPage=newdocumentpagewrapper(page,newpage,PageSize,new Rect(PageSize),new Rect(page.ContentBox.X,page.ContentBox.Y,page.ContentBox.Width+_Margin.Left+_Margin.Right,page.ContentBox.Height+_Margin.Top+_Margin.Bottom));
    _PageCache[pageNumber]=缓存页面;
    返回缓存页;
    }
    public override bool IsPageCountValid{get{return}Paginator.IsPageCountValid;}
    公共重写int PageCount{get{return}Paginator.PageCount;}
    公共覆盖大小PageSize
    {
    获取{var value=_Paginator.PageSize;返回新大小(value.Width+_Margin.Left+_Margin.Right,value.Height+_Margin.Top+_Margin.Bottom);}
    设置{u Paginator.PageSize=新大小(value.Width-_Margin.Left-_Margin.Right,value.Height-_Margin.Top-_Margin.Bottom);}
    }
    公共重写IDocumentPaginatorSource{get{return}
    }
    /// 
    ///在处理我们返回的页面时,有必要处理包装好的DocumentPaginator返回的页面,
    ///因为否则,我们会因页面.Visual仍在使用而不一致地获得ArgumentException。
    /// 
    类DocumentPageWrapper:DocumentPage
    {
    内部DocumentPageWrapper(DocumentPageOriginalPage、可视、大小pageSize、Rect bleedBox、Rect contentBox)
    :base(可视、页面大小、bleedBox、contentBox)
    {