Ereignisbasierte Änderungen der XPS-Seite | .NET
Was ist der ereignisbasierte Ansatz in der Programmierung?
Der ereignisbasierte Ansatz in der Programmierung ist ein Paradigma, das sich um das Konzept von Ereignissen und der Ereignisbehandlung dreht. In diesem Modell wird der Programmablauf durch Ereignisse bestimmt, bei denen es sich um Benutzeraktionen (wie Mausklicks oder Tastendrücke), vom System generierte Benachrichtigungen oder Nachrichten von anderen Anwendungen handeln kann. Hier sind einige Schlüsselaspekte des ereignisbasierten Ansatzes:
Ereignisse: Ereignisse stellen wichtige Ereignisse in einem Programm dar. Dazu können Benutzerinteraktionen, Datenänderungen oder Nachrichten von anderen Teilen eines Systems gehören. Beispielsweise kann ein Klick auf eine Schaltfläche oder das Laden einer Datei Ereignisse auslösen.
Ereignis-Listener: Um auf Ereignisse zu reagieren, verwenden Programmierer Ereignis-Listener (oder Handler). Dies sind Funktionen oder Methoden, die so definiert sind, dass sie ausgeführt werden, wenn ein bestimmtes Ereignis eintritt. Beispielsweise kann ein Ereignis-Listener so eingerichtet werden, dass er eine Funktion ausführt, wenn ein Benutzer auf eine Schaltfläche klickt.
Asynchrone Ausführung: Das ereignisbasierte Modell unterstützt oft die asynchrone Programmierung, sodass Programme reagieren können, während sie auf das Eintreten von Ereignissen warten. Beispielsweise kann eine Webanwendung weiter ausgeführt werden, während sie auf Daten von einem Server wartet.
Entkopplung: Der ereignisbasierte Ansatz fördert die Entkopplung zwischen verschiedenen Teilen eines Programms. Komponenten können über Ereignisse kommunizieren, ohne die Details der Implementierung der anderen Komponenten kennen zu müssen, wodurch der Code modularer und einfacher zu warten ist.
Häufige Anwendungsfälle: Ereignisgesteuerte Programmierung wird häufig in grafischen Benutzeroberflächen (GUIs), Webanwendungen und Systemen verwendet, die Echtzeitinteraktionen erfordern. Frameworks und Bibliotheken wie Node.js, React und viele andere nutzen ereignisgesteuerte Muster.
Zustandsverwaltung: In einem ereignisgesteuerten System kann die Verwaltung des Zustands von entscheidender Bedeutung sein, da sich die Anwendung je nach Benutzerinteraktionen oder Ereignissen in unterschiedlichen Zuständen befinden kann. Um sicherzustellen, dass sich die Anwendung wie erwartet verhält, werden häufig geeignete Strategien zur Zustandsverwaltung eingesetzt.
Insgesamt ist der ereignisbasierte Ansatz eine leistungsstarke Möglichkeit, Interaktionen und Arbeitsabläufe innerhalb eines Programms zu verwalten, was ihn besonders effektiv für Anwendungen macht, die Reaktionsfähigkeit und Benutzerinteraktion erfordern.
Ereignisse, die während der XPS-Dokumentkonvertierung auftreten
Wenn Sie mithilfe der Aspose.Page-API Änderungen an einer bestimmten Seite eines XPS-Dokuments vornehmen müssen, wählen Sie normalerweise das aktive Dokument aus (wenn die XPS-Datei mehrere Dokumente enthält), wählen Sie die aktive Seite aus und nehmen Sie dann die Änderungen selbst vor .
Angenommen, Sie müssen wiederholte Änderungen an allen Seiten in einer XPS-Datei vornehmen und das Ergebnis dann in PDF oder ein Bildformat konvertieren. Einige Beispiele für solche Änderungen umfassen das Platzieren eines Wasserzeichens über den Seiten oder das Hinzufügen von Navigations-Hyperlinks. Der direkte Weg, solche Änderungen vorzunehmen, besteht darin, die Dokumente im XPS-Paket zu durchsuchen, die Seiten im aktuell aktiven Dokument zu durchsuchen und schließlich Ihre Änderungen anzuwenden. Daher würde der Code zum Ausführen dieser Aufgabe wie folgt aussehen:
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);
Wenn Sie vor den sich wiederholenden Änderungen auch einige unregelmäßige Änderungen vornehmen müssen, kann dieser Ansatz zu Verwirrung oder übermäßigem Durchlaufen von Dokumenten und Seiten führen, ganz zu schweigen davon, dass diese Schleifen etwas umständlich erscheinen. Wenn Sie ein XPS-Dokument in ein PDF oder ein Bild konvertieren, erfolgt der Vorgang Seite für Seite. Wenn der Konvertierungsauftrag bereit ist, die nächste Seite zu verarbeiten, löst er ein „Before-Page“-Ereignis aus. Der Benutzer kann die Behandlung solcher Ereignisse definieren, indem er die Klasse BeforePageSavingEventHandler erweitert und so einige Vorteile nutzt, die im Einführungsabschnitt dieses Artikels beschrieben werden.
Beispiel für das Hinzufügen von Navigations-Hyperlinks
Hier stellen wir ein Beispiel für Navigations-Hyperlinks vor. Und um die Aufgabe etwas komplizierter zu machen, konvertieren wir nur eine Teilmenge aller Seiten in PDF, wie durch die Eigenschaft „PdfSaveOptions.PageNumbers“ angegeben.
Die Event-Handler-Klasse
Unten ist die Erweiterung der Klasse „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}
Die Handler-Klasse sollte wissen, welche Seiten wir als PDF speichern möchten, um die richtigen Hyperlink-Ziele zu erstellen. Daher sollte der Konstruktor die Array-Eigenschaft der Optionen als Argument verwenden. Wenn das Array von Seitenzahlen angegeben ist, erstellen wir eine sortierte Sammlung davon und vermeiden gleichzeitig Duplikate. (Übrigens ist diese Lösung nicht ganz korrekt. Können Sie herausfinden, was zu Inkonsistenzen in der Ausgabe führen könnte?) Wir benötigen außerdem ein „XpsFont“-Objekt, das die Schriftartdaten für den Hyperlink-Text enthält.
In der überschriebenen Methode „Handle()“ geschieht alles. Das Argument der Methode ist ein Objekt, das die Änderungs-API für die aktuelle Seite, die Dokumentnummer innerhalb des XPS-Pakets, die absolute Seitenzahl über alle Dokumente hinweg, die relative Seitenzahl innerhalb des aktuellen Dokuments (die gleich ist) enthält vorherige Nummer, falls sich nur ein Dokument im Paket befindet und die Ausgabeseitennummer (die der absoluten Seitenzahl entspricht, wenn wir das gesamte Paket konvertieren).
Die Logik der folgenden zwei „Wenn“-Blöcke ist recht einfach. Es basiert auf der Analyse des Ereignisarguments „OutputPageNumber“, um gegebenenfalls einige der Links wegzulassen: Die Links [First]
und [Prev]
werden allen Ausgabeseiten außer der ersten hinzugefügt, während die Links „ Die Links [Weiter]
und [Letzte]
werden auf allen Seiten außer der letzten angezeigt. Die Logik ist auch auf beide Fälle zugeschnitten, unabhängig davon, ob Seitenzahlen angegeben sind oder nicht.
Nach den „if“-Blöcken gibt es Code zum Hinzufügen einer Seitenzahl in der unteren rechten Ecke der Seite.
Die letzte Zeile fügt den Gliederungseintrag der Seite hinzu, das Element, das im Navigationsbereich eines PDF-Viewers angezeigt wird (sofern unterstützt).
Der Konvertierungscode
Nachdem nun der Ereignishandler „before-page“ definiert ist, können wir den Code schreiben, der das Dokument konvertiert:
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}
Wir öffnen eine XPS-Datei und instanziieren dann ein Stream-Objekt mit der Schriftartdatendatei. Als nächstes erstellen wir eine Instanz der Klasse „PdfSaveOptions“ und geben die Anzahl der Seiten an, die wir konvertieren müssen. In der nächsten Zeile wird der Ereignishandler „before-page“ über die Sammlungsoption „BeforePageSavingEventHandlers“ mit dem Konvertierungsauftrag „verbunden“.
Jetzt müssen Sie nur noch die Konvertierung in PDF mit der Methode „SaveAsPdf()“ des Dokuments durchführen.
Abschluss
In diesem Artikel haben wir die wichtigsten Punkte des ereignisbasierten Ansatzes in der Programmierung untersucht, die direkte Methode zum Ändern von Seiten eines XPS-Dokuments untersucht und eine fortgeschrittenere und ausgefeiltere Technik kennengelernt, um während des Vorgangs wiederholende Änderungen an allen Ausgabeseiten vorzunehmen Konvertierungsprozess am Beispiel des Einfügens von Navigations-Hyperlinks.
Die vollständigen Beispiele finden Sie in unserem Beispielprojekt.