Изменения страницы XPS на основе событий | .NET

Что такое событийный подход в программировании?

Событийный подход в программировании — это парадигма, которая вращается вокруг концепции событий и их обработки. В этой модели ход выполнения программы определяется событиями, которыми могут быть действия пользователя (например, щелчки мыши или нажатия клавиш), генерируемые системой уведомления или сообщения от других приложений. Вот некоторые ключевые аспекты событийно-ориентированного подхода:

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

События, происходящие во время преобразования документа XPS

Когда вам нужно внести изменения в определенную страницу документа XPS с помощью API Aspose.Page, вы обычно выбираете активный документ (если в файле XPS несколько документов), выбираете активную страницу, а затем сами вносите изменения. .

Теперь предположим, что вам нужно внести повторяющиеся изменения во все страницы файла XPS, а затем преобразовать результат в PDF или формат изображения. Некоторые примеры таких изменений включают размещение водяных знаков на страницах или добавление навигационных гиперссылок. Прямой способ внесения таких изменений включает в себя просмотр документов в пакете XPS, просмотр страниц текущего активного документа и, наконец, применение ваших изменений. Таким образом, код для выполнения этой задачи будет выглядеть следующим образом:

 1for (int i = 1; i <= document.DocumentCount; i++)
 2{
 3    document.SelectActiveDocument(i);
 4    for (j = 1; j <= document.PageCount; j++)
 5    {
 6        document.SelectActivePage(j);
 7        // Your changes ...
 8    }
 9}
10document.SaveAsPdf("file-name.pdf", saveOptions);

Если вам также необходимо внести некоторые нерегулярные изменения перед повторяющимися, этот подход может привести к некоторой путанице или чрезмерному обходу документов и страниц, не говоря уже о том, что эти циклы могут показаться немного громоздкими. Когда вы конвертируете документ XPS в PDF или изображение, процесс происходит страница за страницей. Когда задание преобразования готово к обработке следующей страницы, оно вызывает событие «до страницы». Пользователь может определить обработку таких событий, расширив класс BeforePageSavingEventHandler, тем самым воспользовавшись некоторыми преимуществами, описанными во вводном разделе этой статьи.

Пример добавления навигационных гиперссылок

Здесь мы приведем пример, связанный с навигационными гиперссылками. А чтобы немного усложнить задачу, мы преобразуем в PDF только часть всех страниц, как указано в свойстве PdfSaveOptions.PageNumbers.

Класс обработчика событий

Ниже показано расширение класса BeforePageSavingEventHandler:

 1/// <summary>
 2/// The class to handle the before-page event while converting an XPS document.
 3/// </summary>
 4public class NavigationInjector : BeforePageSavingEventHandler
 5{
 6    // The font in which navigation hyperlinks and page numbers will be displayed.
 7    private readonly XpsFont _font;
 8    // The page numbers to convert.
 9    private readonly SortedList<int, int> _pageNumbers;
10
11    public NavigationInjector(XpsFont font, int[] pageNumbers)
12    {
13        _font = font;
14        if (pageNumbers == null)
15            return;
16
17        // Turn the page number array into a sorted collection of unique values.
18        _pageNumbers = new SortedList<int, int>();
19        foreach (int pn in pageNumbers)
20            _pageNumbers[pn] = 0;
21    }
22
23    public override void Handle(BeforeSavingEventArgs<PageAPI> args)
24    {
25        PageAPI api = args.ElementAPI;
26
27        XpsGlyphs glyphs;
28        // For all pages in the output PDF except the first one...
29        if (args.OutputPageNumber > 1)
30        {
31            // ...insert a hyperlink to the first page...
32            glyphs = api.CreateGlyphs(_font, 15f, 5f, api.Height - 10f, "[First]");
33            glyphs.Fill = api.CreateSolidColorBrush(Color.Blue);
34            glyphs.HyperlinkTarget = new XpsPageLinkTarget(_pageNumbers == null ? 1 : _pageNumbers.Keys[0]);
35            api.Add(glyphs);
36
37            // ...and to the previous page.
38            glyphs = api.CreateGlyphs(_font, 15f, 60f, api.Height - 10f, "[Prev]");
39            glyphs.Fill = api.CreateSolidColorBrush(Color.Blue);
40            glyphs.HyperlinkTarget = new XpsPageLinkTarget(
41                _pageNumbers == null ? args.AbsolutePageNumber - 1 : _pageNumbers.Keys[args.OutputPageNumber - 2]);
42            api.Add(glyphs);
43        }
44
45        // For all pages in the output PDF except the last one...
46        if ((_pageNumbers != null && args.OutputPageNumber < _pageNumbers.Count) ||
47            (_pageNumbers == null && args.OutputPageNumber < api.TotalPageCount))
48        {
49            // ...insert a hyperlink to the next page...
50            glyphs = api.CreateGlyphs(_font, 15f, 110f, api.Height - 10f, "[Next]");
51            glyphs.Fill = api.CreateSolidColorBrush(Color.Blue);
52            glyphs.HyperlinkTarget = new XpsPageLinkTarget(
53                _pageNumbers == null ? args.AbsolutePageNumber + 1 : _pageNumbers.Keys[args.OutputPageNumber]);
54            api.Add(glyphs);
55
56            // ...and to the last page.
57            glyphs = api.CreateGlyphs(_font, 15f, 160f, api.Height - 10f, "[Last]");
58            glyphs.Fill = api.CreateSolidColorBrush(Color.Blue);
59            glyphs.HyperlinkTarget = new XpsPageLinkTarget(
60                _pageNumbers == null ? api.TotalPageCount : _pageNumbers.Keys[_pageNumbers.Keys.Count - 1]);
61            api.Add(glyphs);
62        }
63
64        // Insert a page number in the bottom-right corner.
65        glyphs = api.CreateGlyphs(_font, 15f, api.Width - 20f, api.Height - 10f, args.OutputPageNumber.ToString());
66        glyphs.Fill = api.CreateSolidColorBrush(Color.Black);
67        api.Add(glyphs);
68
69        // Add an outline entry to display the links to the converted pages in the navigation pane of a PDF viewer.
70        api.AddOutlineEntry(string.Format("Page {0}", args.OutputPageNumber), 1, args.AbsolutePageNumber);
71    }
72}

Класс-обработчик должен знать, какие страницы мы хотим сохранить в формате PDF, чтобы создать правильные цели гиперссылок. Следовательно, конструктор должен принимать в качестве аргумента свойство массива параметров. Если указан массив номеров страниц, мы создаем их отсортированную коллекцию, избегая при этом дубликатов. (Кстати, это решение не совсем точное. Можете ли вы выяснить, что может вызвать несогласованность вывода?) Нам также понадобится объект XpsFont, содержащий данные шрифта для текста гиперссылки.

Все это происходит в переопределенном методе Handle(). Аргументом метода является объект, который содержит API модификации для текущей страницы, номер документа в пакете XPS, абсолютный номер страницы во всех документах, относительный номер страницы в текущем документе (который равен предыдущий номер, если в пакете только один документ) и номер выходной страницы (который равен абсолютному номеру страницы при конвертации всего пакета).

Логика следующих двух блоков if довольно проста. Он основан на анализе аргумента события OutputPageNumber для исключения некоторых ссылок, где это необходимо: ссылки [First] и [Prev] будут добавлены ко всем выходным страницам, кроме первой, а Ссылки [Следующий] и [Последний] появятся на всех страницах, кроме последней. Логика также адаптирована для обоих случаев, независимо от того, указаны номера страниц или нет.

После блоков if в правом нижнем углу страницы находится код для добавления номера страницы.

Последняя строка добавляет запись структуры страницы, элемент, который будет отображаться в панели навигации средства просмотра PDF (если поддерживается).

Код преобразования

Теперь, когда обработчик события «перед страницей» определен, мы можем написать код, преобразующий документ:

 1// The path to the documents directory.
 2string dataDir = RunExamples.GetDataDir_WorkingWithPages();
 3// Open an XPS document
 4using (XpsDocument doc = new XpsDocument(dataDir + "Sample3.xps"))
 5// Create a font
 6using (Stream fontStream = File.OpenRead(dataDir + "arialbd.ttf"))
 7{
 8    // Create options for conversion to PDF
 9    PdfSaveOptions options = new PdfSaveOptions();
10    // Set the filter for the pages that need conversion
11    options.PageNumbers = new int[] { 2, 6, 7, 13 };
12    // Add the event handler that will execute right before the conversion of each page
13    options.BeforePageSavingEventHandlers.Add(new NavigationInjector(doc.CreateFont(fontStream), options.PageNumbers));
14    // Save resultant XPS document
15    doc.SaveAsPdf(dataDir + "ModifyPageOnConversion_out.pdf", options);
16}

Мы открываем файл XPS, а затем создаем экземпляр объекта потока с файлом данных шрифта. Далее мы создаем экземпляр класса PdfSaveOptions и указываем количество страниц, которые нам нужно преобразовать. В следующей строке обработчик событий «до страницы» «подключается» к заданию преобразования через опцию сбора «BeforePageSavingEventHandlers».

Все, что осталось сделать, это запустить преобразование в PDF, используя метод SaveAsPdf() документа.

Заключение

В этой статье мы рассмотрели ключевые моменты событийно-ориентированного подхода в программировании, рассмотрели прямой метод изменения страниц документа XPS и изучили более продвинутый и сложный метод внесения повторяющихся изменений во все выходные страницы во время процесс преобразования на примере вставки навигационных гиперссылок.

Полные примеры можно найти в нашем Пример проекта.

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.