创建具有多种页面尺寸的XPS文档

时间:2018-10-23 22:30:45

标签: .net wpf xps

我正在从XAML元素创建XPS文件。不仅如此,我还创建了XPS文件,每个页面的大小可能不同。观看此最小复制品:

using (Package pkg = Package.Open("out.xps", FileMode.Create))
using (XpsDocument doc = new XpsDocument(pkg))
{
    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
    SerializerWriterCollator collator = writer.CreateVisualsCollator();

    WritePage(816, 1344); // 8.5 x 14
    WritePage(816, 1056); // 8.5 x 11
    WritePage(816, 1344);
    WritePage(816, 1056);

    collator.EndBatchWrite();

    doc.Close();
    pkg.Close();

    void WritePage(double width, double height)
    {
        var element = new Border()
        {
            Width = width,
            Height = height,
            BorderBrush = Brushes.Black,
            BorderThickness = new Thickness(10.0)
        };

        Size size = new Size(width, height);
        element.Measure(size);
        element.Arrange(new Rect(size));
        element.UpdateLayout();

        collator.Write(element);
    }
}

我遇到的问题是我所有页面的大小最终都一样。或更准确地说,与首页大小相同。该文档的页面全部显示为:

<FixedPage ... Width="816" Height="1344">

我解决此问题的第一个尝试是在写书时设置PrintTicket,但没有效果。

稍后进行一些调试,我将问题追溯到WPF方法XpsSerializationManager.SaveAsXml

if (this._simulator == null)
{
    this._simulator = new ReachHierarchySimulator(
        (PackageSerializationManager) this, serializedObject);
}

...

if (this._isBatchMode)
{
    xmlWriter = this._simulator.SimulateBeginFixedPage();
}

在这里,它仅在第一次调用_simulator时初始化SaveAsXml。存储在模拟器中的是serializedObject -我们正在尝试保存的Visual。问题是,此引用会留作以后的调用。

接下来,它调用_simulator.SimulateBeginFixedPage来创建第一个<FixedPage>元素-但由于它具有对原始对象的引用,因此每个页面都具有与该对象相同的大小。

因此,我解决的方法是在每次Write调用之前通过反射更新该引用:

void WritePage(double width, double height)
{
    var element = new Border()
    {
        Width = width,
        Height = height,
        BorderBrush = Brushes.Black,
        BorderThickness = new Thickness(10.0),
        Tag = pageCounter++
    };

    object manager = collator.GetType()
        .GetField("_manager", BindingFlags.Instance | BindingFlags.NonPublic)
        ?.GetValue(collator);

    object simulator = manager?.GetType()
        .GetField("_simulator", BindingFlags.Instance | BindingFlags.NonPublic)
        ?.GetValue(manager);

    simulator?.GetType()
        .GetField("_serializedObject", BindingFlags.Instance | BindingFlags.NonPublic)
        .SetValue(simulator, element);

    Size size = new Size(width, height);
    element.Measure(size);
    element.Arrange(new Rect(size));
    element.UpdateLayout();

    collator.Write(element);
}

但是-我觉得这太奇怪了,可能是我使用WPF时遇到的问题,而不是WPF本身中的错误。有什么我想念的吗?

0 个答案:

没有答案