- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在寻找一种干净的通用方法来描述 XAML FlowDocument 中重复的页眉和页脚,而无需任何代码。它只需要在从 C# 呈现到 XPS 时正确显示。
最佳答案
几个月前我遇到了同样的问题,发现这些链接非常有用: WPF Multipage Reports Part IV Pagination http://www.codeproject.com/KB/WPF/PimpedDocumentPaginator.aspx
我使用的基本技术是通过从 DynamicDocumentPaginator
派生来创建自定义分页器,如下所示:
internal class HeaderFooterPaginator<THeaderModel, TFooterModel> : DynamicDocumentPaginator where THeaderModel : PageNumberModel, new() where TFooterModel : PageNumberModel, new()
{
...
}
在我的例子中,THeaderFooterModel
和 TFooterModel
是 PageNumberModel
类型的子类,因为我需要页眉或页脚才能显示当前页码。
public class PageNumberModel
{
public int PageNumber { get; set; }
}
自定义分页器将大部分工作委托(delegate)给原始 XPS 分页器,因此它将其存储在构造函数中。
THeaderModel
和 TFooterModel
类型允许分页器检索每种类型的 XAML DataTemplates
,这允许您指定布局XAML 中的页眉和页脚,而无需诉诸自定义绘图代码。
在我的代码中,页眉和页脚的大小是固定的,因此在创建分页器时,它会检索页眉和页脚模板以确定要保留多少空间。
在提供的链接中的示例代码中,他们用于为页眉和页脚保留空间的技术是使用缩放变换来缩小原始内容。相反,我告诉原始分页器使用缩小的页面大小,然后将原始分页器生成的页面添加到 ContainerVisual
并设置其 Offset
。如果页眉和页脚的大小是动态的,您可能无法这样做,因为页数会不断变化。
我记得的唯一其他复杂情况是您在添加页眉和页脚时需要使用 Dispatcher
队列(请参阅下面的 AddHeaderOrFooterToContainerAsync
)。否则数据绑定(bind)不起作用。我们稍微颠覆了 WPF 渲染模型以使其正常工作。
如果不包括代码,这一切都很难解释,所以我在下面附上了自定义渲染器代码。我已经删除了一些不相关的东西,所以如果它不能按原样编译,这可能就是原因:-)
请注意,页码偏移量已传入,因为我们的 XPS 文档由多个 FlowDocument 部分组成,并且调用代码会跟踪当前的总页码。
希望这对您有所帮助!
internal class HeaderFooterPaginator<THeaderModel, TFooterModel> : DynamicDocumentPaginator where THeaderModel : PageNumberModel, new() where TFooterModel : PageNumberModel, new()
{
private readonly double _footerHeight;
private readonly DataTemplate _footerTemplate;
private readonly double _headerHeight;
private readonly DataTemplate _headerTemplate;
private Size _newPageSize;
private Size _originalPageSize;
private readonly DynamicDocumentPaginator _originalPaginator;
private readonly int _pageNumberOffset;
private readonly FlowDocument _paginatorSource;
private const double HeaderAndFooterMarginHeight = 5;
private const double HeaderAndFooterMarginWidth = 10;
public HeaderFooterPaginator(int pageNumberOffset, FlowDocument document)
{
if (document == null)
{
throw new ArgumentNullException("document");
}
_paginatorSource = document;
if (_paginatorSource == null)
{
throw new InvalidOperationException("Could not create a clone of the document being paginated.");
}
_originalPaginator = ((IDocumentPaginatorSource) _paginatorSource).DocumentPaginator as DynamicDocumentPaginator;
if (_originalPaginator == null)
{
throw new InvalidOperationException("The paginator must be a DynamicDocumentPaginator.");
}
_headerTemplate = GetModelDataTemplate(typeof (THeaderModel));
_footerTemplate = GetModelDataTemplate(typeof (TFooterModel));
var headerSize = GetModelContentSize(new THeaderModel { PageNumber = int.MaxValue }, _headerTemplate, _originalPaginator.PageSize);
var footerSize = GetModelContentSize(new TFooterModel { PageNumber = int.MaxValue }, _footerTemplate, _originalPaginator.PageSize);
_headerHeight = double.IsInfinity(headerSize.Height) ? 0 : headerSize.Height;
_footerHeight = double.IsInfinity(footerSize.Height) ? 0 : footerSize.Height;
_pageNumberOffset = pageNumberOffset;
SetPageSize(new Size(document.PageWidth, document.PageHeight));
}
private void AddHeaderOrFooterToContainerAsync<THeaderOrFooter>(ContainerVisual container, double areaWidth, double areaHeight, Vector areaOffset, FrameworkTemplate template, int displayPageNumber) where THeaderOrFooter : PageNumberModel, new()
{
if (template == null)
{
return;
}
var visual = GetModelContent(new THeaderOrFooter { PageNumber = displayPageNumber }, template);
if (visual != null)
{
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
visual.Measure(_originalPageSize);
visual.Arrange(new Rect(0, 0, areaWidth, areaHeight));
visual.UpdateLayout();
var headerContainer = new ContainerVisual { Offset = areaOffset };
headerContainer.Children.Add(visual);
container.Children.Add(headerContainer);
}));
}
}
public override void ComputePageCount()
{
_originalPaginator.ComputePageCount();
}
private static void FlushDispatcher()
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.ApplicationIdle, new DispatcherOperationCallback(delegate { return null; }), null);
}
private static FrameworkElement GetModelContent(object dataModel, FrameworkTemplate modelTemplate)
{
if (modelTemplate == null)
{
return null;
}
var content = modelTemplate.LoadContent() as FrameworkElement;
if (content == null)
{
return null;
}
content.DataContext = dataModel;
return content;
}
private static Size GetModelContentSize(object dataModel, FrameworkTemplate modelTemplate, Size availableSize)
{
var content = GetModelContent(dataModel, modelTemplate);
if (content == null)
{
return Size.Empty;
}
FlushDispatcher();
content.Measure(availableSize);
return content.DesiredSize;
}
private DataTemplate GetModelDataTemplate(Type modelType)
{
var key = new DataTemplateKey(modelType);
return _paginatorSource.TryFindResource(key) as DataTemplate;
}
public override ContentPosition GetObjectPosition(object value)
{
return _originalPaginator.GetObjectPosition(value);
}
public override DocumentPage GetPage(int pageNumber)
{
if (!_originalPaginator.IsPageCountValid)
{
ComputePageCount();
}
var originalPage = _originalPaginator.GetPage(pageNumber);
var newPage = new ContainerVisual();
var displayPageNumber = _pageNumberOffset + pageNumber;
var internalWidth = _originalPageSize.Width - 2*HeaderAndFooterMarginWidth;
AddHeaderOrFooterToContainerAsync<THeaderModel>(newPage, internalWidth, _headerHeight, new Vector(HeaderAndFooterMarginWidth, HeaderAndFooterMarginHeight), _headerTemplate, displayPageNumber);
var smallerPage = new ContainerVisual();
smallerPage.Children.Add(originalPage.Visual);
smallerPage.Offset = new Vector(HeaderAndFooterMarginWidth, HeaderAndFooterMarginHeight + _headerHeight);
newPage.Children.Add(smallerPage);
AddHeaderOrFooterToContainerAsync<TFooterModel>(newPage, internalWidth, _footerHeight, new Vector(HeaderAndFooterMarginWidth, _originalPageSize.Height - HeaderAndFooterMarginHeight - _footerHeight), _footerTemplate, displayPageNumber);
return new DocumentPage(newPage, _originalPageSize, originalPage.BleedBox, originalPage.ContentBox);
}
public override int GetPageNumber(ContentPosition contentPosition)
{
return _originalPaginator.GetPageNumber(contentPosition);
}
public override ContentPosition GetPagePosition(DocumentPage page)
{
return _originalPaginator.GetPagePosition(page);
}
private void SetPageSize(Size pageSize)
{
_originalPageSize = pageSize;
// Decrease the available page size by the height of the header and footer. The page is offset by the header height later on.
var sizeRect = new Rect(pageSize);
sizeRect.Inflate(-HeaderAndFooterMarginWidth, -(HeaderAndFooterMarginHeight + _footerHeight/2 + _headerHeight/2));
_originalPaginator.PageSize = _newPageSize = sizeRect.Size;
// Change page size of the document to the size of the content area
_paginatorSource.PageHeight = _newPageSize.Height;
_paginatorSource.PageWidth = _newPageSize.Width;
}
public override bool IsPageCountValid
{
get { return _originalPaginator.IsPageCountValid; }
}
public override int PageCount
{
get { return _originalPaginator.PageCount; }
}
public override Size PageSize
{
get { return _newPageSize; }
set { SetPageSize(value); }
}
public override IDocumentPaginatorSource Source
{
get { return _originalPaginator.Source; }
}
}
关于c# - 呈现为 XPS 时如何创建带有页眉和页脚的 Xaml FlowDocument?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5172781/
我想将页 footer 分放在文档的每一页上,除了第一页。 我通过扩展 TCPPDF 类并覆盖其页脚方法来创建我的自定义页脚。 然后根据文档并使用以下示例,我明白我应该使用 SetPrintHeade
我的页面分为 3 个部分。 页眉 主要 和页脚。 header 固定在顶部,大小为 109px,边框高 6px,因此 main 到顶部的边距为 109px。我希望 main 扩展到 heade
我正在构建一个网站,其中每个页面都有一个 , 和一个 . 据我了解,应用程序的入口点应包括这三个组件,并且应根据用户所在的路线呈现一个或多个附加组件。 我已经像这样构建了我的入口点: App.js
谁能告诉我为什么Footer出现在页面顶部,而我看不到Header或LayoutDiv9? 这是我添加的第二个 CSS 表,第一个是自动添加的 Fluid Grid Layout CSS 表,我根本没
我的应用程序中有这个页面: http://actibities-uniongr.rhcloud.com/pages/view-demo 如果您将浏览器的窗口缩短到小于 1000 像素并水平滚动,您会看
这个问题已经有答案了: Python command line interaction library? (3 个回答) 已关闭10 年前。 如何创建一个包含静态页眉和页脚的 Python 脚本,如下
我正在努力为我们的 Mediboard 元素提供完整的 HTML 页眉/页脚打印功能。 从长远来看,我知道 CSS3 页面媒体模块将满足我的需求,但这至少需要两三年时间。 所以我试着让它与 CSS2
我可以在每页上打印页眉,但我不熟悉打印页边距。我认为 @page css 可以工作,但它似乎不会影响页边距。如果我在正文上设置边距,它在第一页上有效,但后续页面默认从上边距开始,将页眉放在文本顶部。
有什么办法,就像 WordPress 一样,创建 header.php、theme-file.php 和 footer.php,然后使用钩子(Hook)将它们组合起来?对我来说仍然复制皮肤文件似乎
我正在努力解决以下问题。我有一个 UICollectionView,它的布局的页眉和页脚引用大小设置为一个值(比如 40.0)。当我删除/插入单元格并且集合 View 位于页眉和页脚不在屏幕上的位置时
我是 javascript 新手。我想使用 ajax 加载我的网站主模板文件(页眉、页脚、侧边栏)。我的布局文件如下所示。 布局.php header(); $ret .= $app->side
这是我的代码。内容图像曾短暂地工作,但现在消失了。 试图让Header只出现在页面顶部,图片高度为1000px。页面底部的页脚,图像高度为 1000px。内容图像需要重复以适合内容。这是一个博客,所以
我正在尝试将以下图像添加为网站内容的背景: http://webbos.co/vibration/wp-content/themes/vibration-child-theme/images/back
如何更改样式表中的页眉/页脚文本颜色? 我试过了,没有结果: footer: { parent: normal, alignment: TA_CENTER, textColor: red
我有以下 HTML,它有一个页眉、一个可滚动的内容和一个页脚,并且工作正常。 我想添加到此 HTML 的是一个包装所有三个 div 的表单,问题是一旦我用标签包装 div,布局就会中断。有什么建议吗?
我使用 jQuery 创建了具有不同状态的页眉和页脚导航。单击页脚导航时,我在更新页眉导航时遇到问题。例如,当用户单击页脚导航中的列表 1 时,我希望页眉导航也更新为相同的选择。我包含了一个 jsfi
我需要创建一个网页,其中包含正常页眉 + 粘性页脚 + 垂直拉伸(stretch)的流体内容。但是,这些位置不能是绝对的,因为我需要 780 像素的页面最小高度。 我设法使用表格完成了此操作,但我真的
我知道这可能是一件非常简单的事情,但除了很棒的 Stack Overflow 社区之外,我不知道有谁可以帮助我解决我的问题。我已经有一段时间没有在这种程度上使用 HTML/CSS 了。 我正在尝试为我
我前段时间做了一个wordpress网站。我今天刚刚看了一眼,由于某种原因,这个标志已经向东传播了。它已经厌倦了 clearfix 的 float 、文本对齐和边距:0 自动。谁能告诉我发生了什么,或
我需要帮助创建包含#header、#footer 和#main 的div 的代码。我只是不确定它在代码中的位置。我创建了一个带有 css 样式表的简单 html 页面。我并不是要任何人为我编写代码,因
我是一名优秀的程序员,十分优秀!