【问题标题】:Load XpsDocument from a .XPS file into existing FixedDocument将 XpsDocument 从 .XPS 文件加载到现有的 FixedDocument
【发布时间】:2014-01-25 02:36:13
【问题描述】:

我正在尝试从磁盘加载 XPS 文件并将其打印为我创建的内存文档中的 FixedDocumentFixedDocumentSequence 的一部分。它们需要作为一个序列打印,因为它们是双面打印的。

这是我迄今为止最好的尝试:

// create my memory FixedDocument (a packing slip)
DocumentReference mainDocRef = GetMainDoc();  // created in memory

// load XPS document from file (to print on the back)
XpsDocument xpsDoc = new XpsDocument("flyer.xps", FileAccess.Read);
var docSequenceFromFile = xpsDoc.GetFixedDocumentSequence();
var xpsDocRef = docSequenceFromFile.References.First();

// try to combine together
FixedDocumentSequence documentSequence = new FixedDocumentSequence();
documentSequence.References.Add(mainDocRef);
documentSequence.References.Add(xpsDocRef);     // THROWS EXCEPTION

// print
XpsDocumentWriter xps = PrintQueue.CreateXpsDocumentWriter(printQueue);
xps.Write(documentSequence, ticket);

我总是以例外结束:

InvalidOperationException:附加信息:指定元素已经是另一个元素的逻辑子元素。先断开连接。

我已经尝试了几种方法来做到这一点,但总是以这样的错误结束

如何加载XpsDocument 并将其作为第二页打印在我在内存中创建的FixedDocumentSequence 中?

【问题讨论】:

  • WAG,但在引用的 FixedDocumentSequence 上调用 RemoveLogicalChild。这都是WPF,顺便说一句。在 WPF 中,元素最多有一个“逻辑父级”,就像拥有您在代码中使用的实例的对象一样(可视化树是从逻辑树创建的,并且可以不同)。要执行您想要的操作,您需要断开孩子与父母的连接,以便您可以将其重新连接到不同的父母。我认为我链接到的方法应该这样做。
  • @Will 这是一个受保护的方法
  • 不仅受到保护,而且在内部
  • @Simon_Weaver:这就是为什么我说它是 WAG(疯狂的猜测)。但是,校长还是一样的。您必须断开孩子与父母的联系。时期。如果没有示例项目,我无法确定地告诉您如何做到这一点。您可以使用 LogicalTreeHelper 来查找父级,然后检查它以获取可用于断开两者的方法或属性。对于不同的框架类型,它是不同的。例如,要断开 ContentControl,只需将其 Content 属性清空即可。而且,嘿,更糟的是,利用反射偷偷躲在窗帘后面。

标签: .net xaml xps xpsdocument


【解决方案1】:

西蒙韦弗,

由于我不完全知道 GetMainDoc() 方法返回的内容,因此我已将其排除在外,只是注释掉了 mainDocRef 引用,但这似乎微不足道,因为您的问题是将加载的 xps 文件添加到您的 documentSequencemainDocRef 与问题有些无关(如果我错了,请纠正我)。

现在问题是xpsDoc 被加载到另一个元素(文档),我们必须将其分离为异常状态。但是,这样做的能力受到internal 方法的保护。据说最简单的方法是枚举文档的所有页面,并从被枚举页面的源到新文档创建一个新页面。

最终的代码看起来像..(代码注释)

//DocumentReference mainDocRef = GetMainDoc();  // created in memory. commented as I dont have a reference to what this object contains.

//create our new document reference to add the pages to
DocumentReference newDocReference = new DocumentReference();

// load XPS document from file (to print on the back)
using (XpsDocument xpsDoc = new XpsDocument(@"flyer.xps", FileAccess.Read))
{
    var docSequenceFromFile = xpsDoc.GetFixedDocumentSequence();
    var xpsDocRef = docSequenceFromFile.References.First();

    //get the fixed document to enumerate
    FixedDocument xpsFixedDoc = xpsDocRef.GetDocument(false);

    //get the fixed document to add to
    FixedDocument newFixedDoc = new FixedDocument();

    //set the new document reference
    newDocReference.SetDocument(newFixedDoc);

    //enumerate each page of the fixed document
    foreach (PageContent page in xpsFixedDoc.Pages)
    {
        PageContent newPageContent = new PageContent();
        newPageContent.Source = page.Source;
        ((IUriContext)newPageContent).BaseUri = ((IUriContext)page).BaseUri;
        newPageContent.GetPageRoot(true);
        newFixedDoc.Pages.Add(newPageContent);
    }
}

// try to combine together.
FixedDocumentSequence documentSequence = new FixedDocumentSequence();

//documentSequence.References.Add(mainDocRef); <<-- commented out, re-add after tests

//add the new document reference
documentSequence.References.Add(newDocReference);     

// print
XpsDocumentWriter xps = PrintQueue.CreateXpsDocumentWriter(printQueue);
xps.Write(documentSequence, ticket);

mainDocRef = null;
newDocReference = null;

现在要注意的一件事是XpsDocumentPrintQueue 继承自IDisposable。 (不需要告诉你在那里做什么)。

现在GetMainDoc() 可能仍然存在问题,但由于未发布对此方法的引用,因此我无法在此处测试任何错误。告诉我进展如何。

干杯。妮可

【讨论】:

    猜你喜欢
    • 2012-03-15
    • 2016-12-07
    • 2012-02-03
    • 2011-07-16
    • 1970-01-01
    • 2020-02-19
    • 2020-05-10
    • 1970-01-01
    • 2012-07-17
    相关资源
    最近更新 更多