Come abbiamo visto nell'Introduzione al Print Contract, stampare nativamente da una applicazione Windows Store non è semplicissimo e richiede una serie di passaggi per preparare il contenuto da stampare, renderlo visibile nell'anteprima di stampa, gestire l'interazione con i vari eventi che il Device Charm invia all'applicazione.
In questo articolo ci spingiamo ancora oltre vedendo insieme come modificare le opzioni di stampa e come creare impostazioni custom.
Modificare le opzioni di stampa
Nelle lezioni precedenti abbiamo utilizzato le impostazioni di default. In un'applicazione Windows Store, tuttavia, è anche possibile modificare il valore iniziale delle opzioni mostrate nel pannello di preview, ovvero decidere quali e in che ordine mostrarle, e persino creare opzioni custom (quest'ultima possibilità è invece preclusa per le applicazioni in HTML5/JavaScript).
In particolare, la classe PrintTaskOptions
permette di:
- impostare i valori iniziali delle opzioni che mostrate all'utente nel pannello di stampa (come la scelta di un certo tipo di formato piuttosto che un altro);
- recuperare il valore corrente delle opzioni di stampa, così come modificate dall'utente sempre nel pannello di preview;
- creare opzioni di stampa custom.
In questo paragrafo ci occuperemo del primo aspetto, mentre per gli altri due si rinvia ai paragrafi successivi.
Il prossimo snippet mostra come utilizzare la classe PrintTaskOptions
per impostare il valore iniziale di alcune delle più comuni opzioni di stampa, come l'orientamento e le dimensioni della carta, la qualità e il colore, ecc. (Per l'elenco completo delle opzioni disponibili si rinvia alla documentazione su MSDN).
private void PrintManager_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
PrintTask printTask = null;
printTask = args.Request.CreatePrintTask("Html.it Print Sample in C#", (sourceRequested) =>
{
printTask.Completed += OnPrintTaskCompleted;
printTask.Options.Orientation = PrintOrientation.Landscape;
printTask.Options.ColorMode = PrintColorMode.Grayscale;
printTask.Options.MediaSize = PrintMediaSize.IsoA4;
printTask.Options.PrintQuality = PrintQuality.Normal;
printTask.Options.MediaType = PrintMediaType.Plain;
sourceRequested.SetSource(this._documentSource);
});
}
È anche possibile definire quali opzioni di stampa verranno visualizzate nel pannello di preview e in quale ordine. Per far questo, è necessario recuperare l'oggetto PrintTaskOptionDetails
del print task corrente tramite il metodo GetFromPrintTaskOptions
, ottenere una reference alla proprietà DisplayedOptions
e aggiungere una ad una alla collection le opzioni che vogliamo vengano mostrate all'utente, nello stesso ordine in cui vogliamo che appaiano.
Ciascuna opzione è aggiunta alla collection tramite la classe StandardPrintTaskOptions
, la quale espone i nomi canonici per le opzioni rappresentate dalla classe PrintTaskOptions
.
private void PrintManager_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
PrintTask printTask = null;
printTask = args.Request.CreatePrintTask("Html.it Print Sample in C#", (sourceRequested) =>
{
printTask.Completed += OnPrintTaskCompleted;
PrintTaskOptionDetails detailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(printTask.Options);
IList<string> displayedOptions = detailedOptions.DisplayedOptions;
displayedOptions.Clear();
displayedOptions.Add(StandardPrintTaskOptions.Orientation);
displayedOptions.Add(StandardPrintTaskOptions.ColorMode);
displayedOptions.Add(StandardPrintTaskOptions.Collation);
displayedOptions.Add(StandardPrintTaskOptions.MediaSize);
displayedOptions.Add(StandardPrintTaskOptions.PrintQuality);
displayedOptions.Add(StandardPrintTaskOptions.MediaType);
printTask.Options.Orientation = PrintOrientation.Landscape;
printTask.Options.ColorMode = PrintColorMode.Grayscale;
printTask.Options.Collation = PrintCollation.Uncollated;
printTask.Options.MediaSize = PrintMediaSize.IsoA4;
printTask.Options.PrintQuality = PrintQuality.Normal;
printTask.Options.MediaType = PrintMediaType.Default;
sourceRequested.SetSource(this._documentSource);
});
}
Nella prossima immagine, il pannello di preview mostra le opzioni definite via codice, nello stesso ordine con cui sono state aggiunte alla collection. Come si può vedere, le opzioni ColorMode
e PrintQuality
, non supportate da questa specifica periferica, sono state semplicemente ignorate.
Prima di passare oltre, è importante aggiungere che, sebbene ognuna delle opzioni di stampa esponga il proprio specifico range di possibili valori (codificati in altrettanti enum, come PrintOrientation
, PrintColorMode
, ecc), tutte le opzioni presentano lo stesso modello generale per gestire situazioni comuni. Questo modello include tre valori comuni alle varie opzioni:
- DefaultValue
- NotAvailable
- PrinterCustom
Assegnando a una delle opzioni di stampa il valore DefaultValue
, stiamo in realtà dicendo alla periferica di stampa di usare il valore di default previsto per questa opzione, quale che sia (in altri termini, lasciamo alla periferica il compito di determinare il valore per questa opzione, come si può vedere nella precedente immagine per quanto riguarda l'opzione MediaType
). Se invece il valore di DefaultValue
non è assegnato via codice, ma recuperato in lettura dal sistema, significa che il valore di quella opzione non è stato ancora determinato.
Se un'opzione presenta il valore di NotAvailable
, significa che tale opzione non è supportata dalla periferica selezionata. Non è possibile ovviamente impostare un'opzione sul valore NotAvailable
: in questo caso, viene sollevata un'eccezione di tipo ArgumentException
.
Infine, se un'opzione presenta il valore di PrinterCustom
, vuol dire che la periferica selezionata supporta quella particolare funzionalità, ma che il valore correntemente selezionato è specifico per quella particolare stampante (ad esempio, dimensioni custom della pagina).
Reagire alle modifiche da parte dell'utente alle opzioni di stampa
Nel paragrafo precedente abbiamo visto come impostare il valore iniziale delle opzioni di stampa. L'utente può in ogni caso modificare questo valore nella finestra di preview, per cui è importante che la nostra applicazione sia in grado di reagire a queste modifiche, in modo da "aggiustare" di conseguenza la formattazione e l'impaginazione del documento. Per far questo, la classe PrintTaskOptionDetails
espone l'evento OptionChanged
, il quale viene sollevato ogni volta che l'utente modifica una delle proprietà nella finestra di stampa.
private void PrintManager_PrintTaskRequested(PrintManager sender,
PrintTaskRequestedEventArgs args)
{
PrintTask printTask = null;
printTask = args.Request.CreatePrintTask(
"HTML.it Print Sample in C#",
(sourceRequested) =>
{
// (codice omesso)
detailedOptions.OptionChanged += OnOptionChanged;
sourceRequested.SetSource(this._documentSource);
});
}
Nel corrispondente handler dell'evento, è possibile sfruttare il metodo InvalidatePreview
esposto dall'oggetto PrintDocument
per invalidare la preview corrente, costringendo il sistema a sollevare l'evento Paginate
e dunque con la possibilità di modificare il documento in base alle nuove opzioni:
private async void OnOptionChanged(PrintTaskOptionDetails sender, PrintTaskOptionChangedEventArgs args)
{
string optionId = args.OptionId as String;
if (!String.IsNullOrEmpty(optionId))
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this._printDocument.InvalidatePreview();
});
}
}
Ad esempio, possiamo sfruttare l'evento OptionChanged
per modificare il documento in base all'orientamento della pagina, come mostrato nel seguente codice:
private void PrintDocument_Paginate(object sender, PaginateEventArgs e)
{
(codice omesso)
var header = (StackPanel)this._pageToPrint.FindName("DocumentHeader");
var footer = (StackPanel)this._pageToPrint.FindName("DocumentFooter");
header.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
footer.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
if (printingOptions.Orientation == PrintOrientation.Landscape)
footer.Visibility = Windows.UI.Xaml.Visibility.Visible;
else if (printingOptions.Orientation == PrintOrientation.Portrait)
header.Visibility = Windows.UI.Xaml.Visibility.Visible;
this._pageList.Add(this._pageToPrint);
this._printDocument.SetPreviewPageCount(this._pageList.Count, PreviewPageCountType.Intermediate);
}
In questo semplice esempio, il codice gioca con l'header e il footer della pagina in base all'orientamento della pagina:
Creare opzioni di stampa custom
Come abbiamo accennato, è anche possibile sfruttare la classe PrintTaskOptions
per aggiungere al pannello di preview opzioni di stampa personalizzate:
private void PrintManager_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
PrintTask printTask = null;
printTask = args.Request.CreatePrintTask("Html.it Print Sample in C#", (sourceRequested) =>
{
PrintTaskOptionDetails detailedOptions =
PrintTaskOptionDetails.GetFromPrintTaskOptions(printTask.Options);
IList<string> displayedOptions = detailedOptions.DisplayedOptions;
// (codice omesso)
PrintCustomItemListOptionDetails customOption = detailedOptions.CreateItemListOption("Watermark", "Watermark");
customOption.AddItem("visible", "Show watermark");
customOption.AddItem("collapsed", "Hide watermark");
displayedOptions.Add("Watermark");
// (codice omesso)
});
}
Il codice utilizza il metodo CreateItemListOption
della classe PrintTaskOptionDetails
per creare una nuova opzione personalizzata di tipo PrintCustomItemListOptionDetails
e denominata "Watermark".
Il metodo AddItem
consente di specificare i valori che questa opzione può assumere, ossia "Visible" e "Collapsed" nel nostro caso, e il testo da mostrare all'utente nella corrispondente drop-down list visualizzata nel pannello di preview (rispettivamente, "Show watermark" e "Hide watermark"). La prossima immagine mostra il pannello di preview con la nuova opzione custom.
È possibile recuperare in un secondo momento il valore selezionato dall'utente (sempre sfruttando l'evento OptionChanged
) tramite il metodo GetFromPrintTaskOptions
della classe PrintTaskOptionDetails
, in modo da modificare di conseguenza il documento da stampare, come mostrato nel prossimo snippet:
PrintTaskOptionDetails printDetailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(printingOptions);
String wm = (printDetailedOptions.Options["Watermark"].Value as String).ToLowerInvariant();
if (wm == "visible")
{
// aggiorna il documento
}
Come abbiamo visto, è possibile personalizzare il comportamento dell'anteprima di stampa personalizzandone le opzioni. È anche possibile creare opzioni di stampa custom da controllare via codice durante il processo di stampa.