Как создать XPS-документ?

Я хотел бы создать документ XPS для хранения и печати.

Каков самый простой способ создать документ XPS (например, с простой сеткой с некоторыми данными внутри) в моей программе и передать его?


person Sam    schedule 09.12.2008    source источник
comment
Это также может помочь: http://blogs.msdn.com/fyuan/archive/2005/09/12/463887.aspx   -  person noesgard    schedule 11.12.2008


Ответы (3)


В этом нет ничего легкого. Но это может быть сделано. У меня есть пример кода (к сожалению, все еще глючный) и информация в моем блоге для создания документа в памяти.

Вот некоторый код, который я набросал для тестирования, который инкапсулирует все (он записывает коллекцию FixedPages в документ XPS в памяти). Он включает код для сериализации документа в массив байтов, но вы можете пропустить эту часть и просто вернуть документ:

public static byte[] ToXpsDocument(IEnumerable<FixedPage> pages)
{
    // XPS DOCUMENTS MUST BE CREATED ON STA THREADS!!!
    // Note, this is test code, so I don't care about disposing my memory streams
    // You'll have to pay more attention to their lifespan.  You might have to 
    // serialize the xps document and remove the package from the package store 
    // before disposing the stream in order to prevent throwing exceptions
    byte[] retval = null;
    Thread t = new Thread(new ThreadStart(() =>
    {
        // A memory stream backs our document
        MemoryStream ms = new MemoryStream(2048);
        // a package contains all parts of the document
        Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
        // the package store manages packages
        Uri u = new Uri("pack://TemporaryPackageUri.xps");
        PackageStore.AddPackage(u, p);
        // the document uses our package for storage
        XpsDocument doc = new XpsDocument(p, CompressionOption.NotCompressed, u.AbsoluteUri);
        // An xps document is one or more FixedDocuments containing FixedPages
        FixedDocument fDoc = new FixedDocument();
        PageContent pc;
        foreach (var fp in pages)
        {
            // this part of the framework is weak and hopefully will be fixed in 4.0
            pc = new PageContent();
            ((IAddChild)pc).AddChild(fp);
            fDoc.Pages.Add(pc);
        }
        // we use the writer to write the fixed document to the xps document
        XpsDocumentWriter writer;
        writer = XpsDocument.CreateXpsDocumentWriter(doc);
        // The paginator controls page breaks during the writing process
        // its important since xps document content does not flow 
        writer.Write(fDoc.DocumentPaginator);
        // 
        p.Flush();

        // this part serializes the doc to a stream so we can get the bytes
        ms = new MemoryStream();
        var writer = new XpsSerializerFactory().CreateSerializerWriter(ms);
        writer.Write(doc.GetFixedDocumentSequence());

        retval = ms.ToArray();
    }));
    // Instantiating WPF controls on a MTA thread throws exceptions
    t.SetApartmentState(ApartmentState.STA);
    // adjust as needed
    t.Priority = ThreadPriority.AboveNormal;
    t.IsBackground = false;
    t.Start();
    //~five seconds to finish or we bail
    int milli = 0;
    while (buffer == null && milli++ < 5000)
        Thread.Sleep(1);
    //Ditch the thread
    if(t.IsAlive)
        t.Abort();
    // If we time out, we return null.
    return retval;
}

Обратите внимание на дерьмовый код многопоточности. Вы не можете сделать это в потоках MTA; если вы находитесь в потоке STA, вы также можете избавиться от этого.

person Community    schedule 09.12.2008
comment
Интересный код тайм-аута потока - по какой причине вы не использовали вместо этого t.Join(5000)? Я все еще пытаюсь понять остальное :) - person Sam; 09.12.2008
comment
Будет ли этот код компилироваться/работать в .NET 4? Я вижу, что средство записи переменных определено дважды в одной и той же области, и доступ к элементам в коллекции FixedPage будет осуществляться из другого потока, отличного от того, в котором они созданы. - person Michael; 16.04.2012
comment
Я пробовал этот фрагмент кода и получаю сообщение об ошибке: Параметр имеет неожиданный тип «System.String». Ожидаемый тип — «System.Windows.Documents.FixedPage». Имя параметра: значение в строке ((IAAddChild)pc).AddChild(fp); Как я могу решить эту проблему? - person Sudha; 02.04.2013
comment
@sudha вы пытаетесь передать строку вместо FixedPage. Если вы не можете понять, что с этим не так, у меня нет для вас помощи. - person ; 02.04.2013
comment
@ Не могли бы вы помочь мне создать FixedPage? Я так и не понял как он создается.. - person Sudha; 03.04.2013
comment
@Sudha, прочитайте документы, попробуйте сами, и если у вас возникнут проблемы, задайте вопрос. - person ; 03.04.2013
comment
@ Я пробовал это, но я не знаю, как создавать страницы IEnumerable‹FixedPage›. Сначала я указал путь к файлу в виде страниц. Но позже я получил некоторую информацию о FixedPage от msdn.microsoft. .com/ru-ru/library/. Но я не смог создать FixedPage из информации, полученной по этой ссылке. - person Sudha; 04.04.2013
comment
@Sudha да, это когда удобно иметь программиста. Я предлагаю вам нанять одного. - person ; 04.04.2013
comment
@Will Извини.. Я не понял тебя.. программист для чего? - person Sudha; 04.04.2013
comment
Некоторые части этого кода помогли мне решить проблему. Спасибо! - person krflol; 31.10.2019

Если вы работаете в .NET (v2 или более поздней версии), вы можете очень легко создать действительный документ XPS из визуального элемента WPF.

Например, взгляните на этот мой пост в блоге:

http://nixps.blogspot.com/2008/12/wpf-to-pdf.html

В этом примере я создаю визуальный элемент WPF и преобразовываю его в файл XPS перед дальнейшей обработкой.

Если вы не работаете в .NET или хотите больше контролировать вывод XPS, я бы посоветовал вам использовать библиотеку (например, NiXPS SDK). Это намного проще кодировать и гораздо меньше подвержено ошибкам, чем самостоятельное написание XML-конструкций (и правильное управление ресурсами и т.д.).

person nixps    schedule 09.12.2008
comment
Ссылка на ваш блог не работает, может быть, вместо этого вы скопируете пример кода в свой ответ? - person Sam; 09.12.2008
comment
Скопируйте и вставьте URL-адрес вместо того, чтобы следовать ему, это просто неверный href. Он прекрасно показывает, как создать XPS-файл из визуального элемента WPF. - person Kristof Van Landschoot; 11.12.2008
comment
WPF (Windows Presentation Foundation) не выпускался до .NET Framework 3.0 (с Windows Vista). - person Ian Boyd; 08.02.2012
comment
Примечание: NiXPS SDK стоит денег (750 € — самый дешевый пакет на данный момент). - person itsho; 17.05.2015
comment
NiXPS кажется мертвым на данный момент. На главной странице nixps.com отображается пустая страница, а последний раз новости обновлялись в 2010 году (nixps.com/news.php?id=1) - person Patrick D'Souza; 08.06.2015

Все это на самом деле XML. Если вам удобно работать с файлами XML, у вас не должно возникнуть проблем с документами XPS. Вот простой учебник, который я использовал в прошлом, чтобы начать:

http://blogs.ocrasoft.nl/jeroenveurink/?p=21

person BFree    schedule 09.12.2008
comment
странный. Но определенно один из способов, которым вы можете это сделать. Я бы не советовал делать это таким образом, если вы не понимаете спецификацию документа XPS. - person ; 09.12.2008
comment
Создаете причудливый XML-документ, сжатый в zip-архив? Не совсем то, что я имел в виду, когда писал «самый простой способ» :) - person Sam; 09.12.2008
comment
Этот учебник все еще доступен где-нибудь? Блога нет, но мне очень интересно... - person Mladen Mihajlovic; 30.01.2021