Passa ai contenuti principali

Appunti di WPF – Sesta Puntata – Gestire l’applicazione

Un’applicazione WPF, in maniera analoga a quanto accade per un’applicazione Windows Forms, ha un ben determinato ciclo di vita.

Come già visto nei tutorial precedenti, in un progetto WPF troviamo un file denominato Application.xaml (e relativo code behind Application.xaml.vb). Questo file descrive la classe che incapsula il comportamento e le proprietà della nostra applicazione WPF.

In particolare in questo file xaml possono trovare posto quelle risorse che utilizzeremo all’interno dell’applicazione e nel file di code behind possiamo gestire quegli eventi caratteristici del ciclo di vita dell’applicazione.

Prima di analizzare in dettaglio quali sono gli eventi che abbiamo a disposizione nella nostra applicazione WPF, vediamo come è definito il codice XAML del file Application:

  1. <Application x:Class="Application"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     StartupUri="MainWindow.xaml" >
  5.     <Application.Resources>
  6.         
  7.     </Application.Resources>
  8. </Application>

Possiamo vedere che :

· la nostra classe Application deriva dalla classe Application di WPF;

· è impostata la proprietà StartupUri con l’indicazione della finestra principale dell’applicazione;

· prevede una collezione di risorse (vuota nell’esempio riportato).

Vediamo, ora, cosa accade alla nostra classe Application nel momento in cui compiliamo. Se apriamo la cartella dei file obj del progetto WPF (visibile solo se abbiamo attivato l’opzione di visualizzazione di tutti i file di progetto), possiamo osservare la presenza di un file particolare denominato Application.g.vb.

WPF_06_Application_Fig1

Questo file è generato dall’ambiente di sviluppo e, in buona sostanza riporta il seguente codice:

  1. '''<summary>
  2. '''Application
  3. '''</summary>
  4. <System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")>  _
  5. Partial Public Class Application
  6.     Inherits System.Windows.Application
  7.     
  8.     '''<summary>
  9.     '''InitializeComponent
  10.     '''</summary>
  11.     <System.Diagnostics.DebuggerNonUserCodeAttribute()>  _
  12.     Public Sub InitializeComponent()
  13.         
  14.         #ExternalSource("..\..\..\Application.xaml",4)
  15.         Me.StartupUri = New System.Uri("MainWindow.xaml", System.UriKind.Relative)
  16.         
  17.         #End ExternalSource
  18.     End Sub
  19.     
  20.     '''<summary>
  21.     '''Application Entry Point.
  22.     '''</summary>
  23.     <System.STAThreadAttribute(),  _
  24.      System.Diagnostics.DebuggerNonUserCodeAttribute()>  _
  25.     Public Shared Sub Main()
  26.         Dim app As Application = New Application()
  27.         app.InitializeComponent
  28.         app.Run
  29.     End Sub
  30. End Class

Di fatto, questo codice fornisce l’entry point di avvio dell’applicazione (metodo statico Main) e il metodo nel quale si definisce quale è la finestra iniziale (InitializeComponent).

Inoltre possiamo osservare che la classe definita è di tipo parziale, infatti verrà fusa con la classe definita nel code behind Application.xaml.vb.

L’immagine seguente ci mostra quali sono i possibili eventi che possiamo gestire nella classe Application:

WPF_06_Application_Fig2

Tralasceremo, in questo contesto tutti gli eventi di navigazione (tipo Navigated, Navigating, etc., etc.) e ci concentreremo sui rimanenti, decisamente più interessanti in questa fase di apprendimento dell’infrastruttura applicativa:

· Activated : invocato quando una delle finestre dell’applicazione viene attivata, ad esempio se ci spostiamo da un’altra applicazione nella nostra;

· Deactivated : invocato quando, ad esempio, ci spostiamo su di un’altra applicazione facendo perdere il “focus” alla nostra;

· DisptacherUnhandledException : invocato quando una eccezione occorsa all’interno dell’applicazione non viene gestita. Utile per collezionare i dati delle eccezioni e, soprattutto, per non far terminare l’applicazione in maniera poco pulita;

· Exit : invocato nel momento in cui si chiude l’applicazione. Non è possibile, in questo evento annullare la chiusura dell’applicazione stessa ma possiamo scrivere il metodo Main per rilanciare (tramite il metodo Run della classe application) l’applicazione stessa. Nel gestore di questo evento possiamo impostare il codice di uscita dell’applicazione;

· SessionEnding : viene invocato nel momento in cui un utente di windows si disconnette dalla sessione (ad esempio per uno shutdown del sistema);

· Startup : viene invocato nel momento in cui viene eseguito il metodo Run della classe Application.

Per quanto riguarda la modalità con cui un applicazione può essere chiusa, abbiamo a disposizione la proprietà ShutdownMode della classe application che può assumere i seguenti valori:

· OnLastWindowClose : l’applicazione viene chiusa quando l’ultima finestra viene chiusa;

· OnMainWindowClose : l’applicazione viene chiusa quando la finestra principale viene chiusa (è l’impostazione di default);

· OnExplicitShutdown : la chiusura dell’applicazione deve essere effettuata tramite il metodo Shutdown della classe Application.

All’interno del nostro codice possiamo interagire con l’applicazione in esecuzione attraverso la proprietà statica (di sola lettura) Current della classe Application. Ad esempio, vogliamo recuperare la finestra principale dell’applicazione possiamo utilizzare la proprietà Application.Current.MainWindow.

Infine, per concludere, possiamo gestire, all’avvio della nostra applicazione, eventuali argomenti passati all’eseguibile. Gli argomenti sono contenuti nell’array di stringhe Args dell’oggetto StartupEventArgs passato nell’evento di startup dell’applicazione.


Scarica la versione PDF dell'articolo. Scarica la versione Amazon Kindle dell'articolo.

Commenti

Post popolari in questo blog

VB for Dummies: La serializzazione – parte 2

Questo post è la continuazione del precedente post sulla serializzazione. In particolare vedremo la serializzazione SOAP e quella JSON.   Serializzazione SOAP La serializzazione SOAP è demandata alla classe SOAPFormatter contenuta nel namespace System.Runtime.Serialization.Formatters.Soap contenuto nella libreria omonima. Il formatter SOAP risale alle primissime versioni del framework e, purtroppo, da un certo punto in poi, pur non essendo stato dichiarato obsoleto, non è stato portato avanti nello sviluppo e non supporta alcuni tipi di dati usatissimi nel mondo .NET quali i generici e i nullable. Per questo motivo, non possiamo serializzare in formato SOAP (utilizzando il SOAPFormatter) la nostra Fattura (vedi post precedente) poichè questa ha una proprietà di tipo List(Of DettagliFattura) (generico).   Serializzazione JSON Il formato di serializzazione JSON (maggiori info qui ) è un formato testuale molto in voga nelle applicazioni AJAX. Si trata di un mod...

Recensione: Windows Runtime via C#

Può sembrare strano che un VB-ista legga un libro su C#, ma come diceva Sun Tzu: “ Se conosci il tuo nemico, conosci te stesso ”. A parte gli scherzi, il libro vale la pena di essere letto a prescindere dal linguaggio .NET con cui si lavora. Oltre  290 pagine dedicate agli aspetti fondamentali dello sviluppo con Windows Runtime per le Windows Store App. I prerequisiti per poter leggere il libro sono la conoscenza di C# e di Visual Studio e gli autori non danno per scontato quasi nulla partendo dai concetti di base quali il type system e i suoi principi (argomento che di solito è saltato a piedi pari da chi si avvicina al mondo WinRT dal framework completo e che, se non compreso, può dare problemi nello sviluppo quotidiano). Tra i concetti che possiamo definire “core”, troviamo anche i capitoli dedicati all’app packaging e al process model, entrambi ben strutturati e chiari. Già solo questi tre capitoli iniziali giustificherebbero, in un certo qual modo, l’acquisto del libro, ...

Alla scoperta del Kinect : questione di profondità

Nei due precedenti post ( link e link ) abbiamo fatto conoscenza con “l’aggeggio” kinect e visto come sia possibile, in maniera molto semplice, gestire lo stream video proveniente dalla camera. In questo post diamo un’occhiata alla capacità che ha il Kinect di fornire frame in cui l’immagine non è la rappresentazione fedele della realtà che ci circonda ma la rappresentazione bidimensionale della distanza degli oggetti dai sensori di profondità. L’aggeggio, infatti, dispone di un sensore di profondità che è in grado di fornirci la distanza dei punti inquadrati da se stesso e, in più, è in grado di dirci a quale “player” fa riferimento ogni singolo pixel. Ma andiamo con ordine. Per abilitare la ricezione del depth stream è necessario: Istanziare la classe Runtime; Agganciare il gestore dell’evento DepthFrameReady; Inizializzare l’istanza della Runtime scegliendo una delle opzioni che abilitano il sensore di profondità; Aprire lo stream dei dati relativi alla pro...