Modifiche basate su eventi nelle pagine XPS | .NET

Cos’è l’approccio basato sugli eventi nella programmazione?

L’approccio basato sugli eventi nella programmazione è un paradigma che ruota attorno al concetto di eventi e alla loro gestione. In questo modello, il flusso del programma è determinato dagli eventi, che possono essere azioni dell’utente (come clic del mouse o pressione di tasti), notifiche generate dal sistema o messaggi provenienti da altre applicazioni. Ecco alcuni aspetti chiave dell’approccio basato sugli eventi:

Nel complesso, l’approccio basato sugli eventi è un modo potente per gestire interazioni e flussi di lavoro all’interno di un programma, rendendolo particolarmente efficace per le applicazioni che richiedono reattività e interazione con l’utente.

Eventi che si verificano durante la conversione di un documento XPS

Quando è necessario apportare modifiche a una pagina specifica di un documento XPS utilizzando l’API Aspose.Page, in genere si seleziona il documento attivo (se il file XPS contiene più documenti), si seleziona la pagina attiva e quindi si apportano le modifiche.

Ora, supponiamo di dover apportare modifiche ripetute a tutte le pagine di un file XPS e quindi convertire il risultato in PDF o in un formato immagine. Alcuni esempi di tali modifiche includono l’inserimento di una filigrana sulle pagine o l’aggiunta di collegamenti ipertestuali di navigazione. Il modo diretto per apportare tali modifiche consiste nell’attraversare i documenti nel pacchetto XPS, le pagine del documento attivo corrente e infine applicare le modifiche. Pertanto, il codice per eseguire questa operazione sarebbe il seguente:

 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);

Se è necessario apportare modifiche irregolari prima di quelle ricorrenti, questo approccio potrebbe generare confusione o richiedere un’eccessiva esplorazione di documenti e pagine, per non parlare del fatto che questi cicli potrebbero apparire un po’ macchinosi.

Quando si converte un documento XPS in PDF o in un’immagine, il processo avviene pagina per pagina. Quando il processo di conversione è pronto per elaborare la pagina successiva, attiva un evento “before-page”. L’utente può definire la gestione di tali eventi estendendo la classe BeforePageSavingEventHandler, sfruttando così alcuni dei vantaggi descritti nella sezione introduttiva di questo articolo.

Esempio di aggiunta di collegamenti ipertestuali di navigazione

Qui forniremo un esempio relativo al caso dei collegamenti ipertestuali di navigazione. Per rendere il compito un po’ più complicato, convertiremo solo un sottoinsieme di tutte le pagine in PDF, come specificato dalla proprietà PdfSaveOptions.PageNumbers.

La classe gestore eventi

Di seguito è riportata l’estensione della classe BeforePageSavingEventHandler:

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

La classe gestore deve essere a conoscenza delle pagine che desideriamo salvare in PDF per creare i target corretti per i collegamenti ipertestuali. Pertanto, il costruttore deve accettare la proprietà array delle opzioni come argomento. Se viene specificato l’array dei numeri di pagina, ne creiamo una raccolta ordinata, evitando allo stesso tempo i duplicati. (A proposito, questa soluzione non è del tutto accurata. Riesci a capire cosa potrebbe causare incongruenze nell’output?) Avremo anche bisogno di un oggetto XpsFont contenente i dati del font per il testo del collegamento ipertestuale.

Il metodo Handle() sovrascritto è dove avviene tutto. L’argomento del metodo è un oggetto che contiene l’API di modifica per la pagina corrente, il numero del documento all’interno del pacchetto XPS, il numero di pagina assoluto di tutti i documenti, il numero di pagina relativo all’interno del documento corrente (che è uguale al numero precedente nel caso di un solo documento nel pacchetto) e il numero di pagina di output (che è uguale al numero di pagina assoluto quando convertiamo l’intero pacchetto).

La logica dei due blocchi if seguenti è piuttosto semplice. Si basa sull’analisi dell’argomento dell’evento OutputPageNumber per omettere alcuni link ove appropriato: i link [First] e [Prev] verranno aggiunti a tutte le pagine di output tranne la prima, mentre i link [Next] e [Last] appariranno su tutte le pagine tranne l’ultima. La logica è inoltre adattata per entrambi i casi, indipendentemente dal fatto che i numeri di pagina siano specificati o meno.

Dopo i blocchi if, è presente il codice per aggiungere un numero di pagina nell’angolo in basso a destra della pagina.

L’ultima riga aggiunge la voce di struttura della pagina, l’elemento che verrà visualizzato nel riquadro di navigazione di un visualizzatore PDF (se supportato).

Il codice di conversione

Ora che il gestore eventi “before-page” è definito, possiamo scrivere il codice che converte il documento:

 1// Modify page on conversion event.
 2
 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(OutputDir + "ModifyPageOnConversion_out.pdf", options);
16}

Apriamo un file XPS e quindi istanziamo un oggetto stream con il file di dati del font. Successivamente, creiamo un’istanza della classe PdfSaveOptions e specifichiamo il numero di pagine da convertire. La riga successiva è quella in cui il gestore eventi “before-page” viene “connesso” al processo di conversione tramite l’opzione di raccolta BeforePageSavingEventHandlers.

Non resta che eseguire la conversione in PDF utilizzando il metodo SaveAsPdf() del documento.

Conclusione

In questo articolo abbiamo esplorato i punti chiave dell’approccio basato su eventi nella programmazione, esaminato il metodo diretto per modificare le pagine di un documento XPS e appreso una tecnica più avanzata e sofisticata per apportare modifiche ripetute a tutte le pagine di output durante il processo di conversione, utilizzando come esempio l’inserimento di collegamenti ipertestuali di navigazione.

Per gli esempi completi, esplora il nostro Progetto di esempio.

Have any questions about Aspose.Page?



Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.