Salvare lo stato della pagina in Windows Phone 7: Parte 2 - Memorizziamo la posizione

Print Content | More

Come anticipato nel precedente post, abbiamo già imparato come memorizzare il contenuto delle textbox in un tombstone in fase di sospensione di un’applicazione. Un altro aspetto molto importante per garantire continuità nel processo di sospensione / attivazione di un’applicazione è memorizzare l’ultimo controllo attivo, in gergo tecnico quello con il focus. Se l’utilità in un piccolo form può essere minima, diventa invece straordinariamente utile quando i nostri form sono più lunghi di una schermata: l’utente sarebbe costretto a scrollare per il form alla ricerca del campo che stava compilando nel momento in cui ha ricevuto un SMS e ha scelto di rispondere.

Windows Phone 7 ci permette di memorizzare questa informazione tramite una classe, chiamata FocusManager, che ci restituisce l’oggetto correntemente attivo. Il trucco sta nel salvare il nome del controllo attivo in fase di sospensione, per poi reimpostare il focus in fase di riattivazione. In questo tutorial vedremo come realizzare una semplice applicazione che gestisca questa casistica: andremo ad utilizzare il dictionary PhoneApplicationPage.State, dato che si tratta di una informazione relativa allo stato della pagina (come abbiamo visto nel post precedente).

Apriamo il nostro fido Visual Studio e realizziamo un nuovo progetto di tipo Silverlight for Windows Phone: posizioniamoci nel markup della MainPage (MainPage.xaml) e andiamo inserire tre textbox con relative etichette. Questi elementi andranno a comporre un ipotetico form dove faremo inserire al nostro utente nome, cognome e indirizzo e-mail. Ecco il codice da inserire all’interno della ContentGrid:

<StackPanel>
    <TextBlock Text="Insert your name"></TextBlock>
    <TextBox x:Name="txtName"></TextBox>
    <TextBlock Text="Insert your surname"></TextBlock>
    <TextBox x:Name="txtSurname"></TextBox>
    <TextBlock Text="Insert your e-mail address"></TextBlock>
    <TextBox x:Name="txtMail"></TextBox>
</StackPanel>

Ora che abbiamo un semplice form di esempio, possiamo pensare a come salvare il controllo correntemente selezionato. Nel post dedicato al tombstoning avevamo visto che per gestire questo tipo di informazioni dobbiamo utilizzare gli eventi OnNavigatedFrom e OnNavigatedTo. In realtà, per la gestione del focus, questo concetto è vero a metà: dobbiamo si salvare il controllo correntemente attivo quando ci spostiamo dalla pagina corrente, ma non possiamo impostare il focus immediatamente quando vi ritorniamo. Questo perchè, quando si scatena l’evento OnNavigatedTo, la struttura dei controlli della pagina non è ancora stata caricata completamente, perciò Windows Phone non ha modo di impostare il focus. Il trucco è quello di gestire il recupero dell’informazione dal tombstone e il settaggio del focus in un altro evento, Loaded, che si scatena quando l’intera pagina è stata completamente caricata. in questo modo, ci assicuriamo che la struttura dei controlli sia completamente caricata.

Riassumendo, perciò, quello che andremo a fare sarà:

  • Nell’evento OnNavigatedTo, che si scatena quando lasciamo la pagina corrente, andremo a salvare il controllo correntemente attivo.
  • Nell’evento Loaded, che si scatena quando la pagina è stata caricata completamente, andiamo a impostare il focus sul controllo che abbiamo salvato nel tombstone.

Salviamo il controllo attivo

Ecco il codice per implementare questa feature:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);
    object element = FocusManager.GetFocusedElement();
    string elementName=string.Empty;

    if (element != null)
        elementName = ((Control)element).Name;

    if (State.ContainsKey("FocusedElement"))
        State.Remove("FocusedElement");
    State.Add("FocusedElement", elementName);
    
}

Quello che andiamo a fare è salvare in un tombstone un riferimento al controllo correntemente attivo, nello specifico il nome (che nello XAML è definito nella proprietà x:Name). Per fare questo, utilizziamo il già citato FocusManager, che espone il metodo GetFocusedElement() che restituisce, sotto forma di generico object, il controllo attivo. Prima di recuperarne il nome, però, dobbiamo fare un cast dell’oggetto restituito dal FocusManager per convertirlo in un Control, che rappresenta un controllo all’interno della nostra pagina.

A questo punto, siamo pronti per salvare la proprietà Name dell’oggetto restituito in un tombstone: utilizziamo perciò il dictionary PhoneApplicationPage.State, dato che si tratta di un’informazione relativa allo stato della pagina (le pagine di WindowsPhone derivano tutte da PhoneApplicationPage, ecco perchè il dictionary State è disponibile senza specificare alcun namespace o singleton).

Il resto del codice dovrebbe esservi famigliare, dato che abbiamo già lavorato con i tombstone: prima di salvare il nome del dictionary, verifichiamo se una chiave con lo stesso nome esiste già e, in caso, la rimuoviamo.

Recuperiamo il controllo attivo

Ecco il codice per implementare questa feature:

public MainPage()
{
    InitializeComponent();
    Loaded += new RoutedEventHandler(MainPage_Loaded);
}

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
     if (State.ContainsKey("FocusedElement"))
    {
        Control focusedElement = (Control)this.FindName(State["FocusedElement"].ToString());
        if (focusedElement!=null)
            focusedElement.Focus();
    }
}

In caso venga trovato nel dictionary State un oggetto con la chiave da noi utilizzata (nell’esempio, FocusedElement), andiamo a recuperare il nome del controllo salvato dal tombstone. Utilizziamo poi la funzione FindName messa a disposizione del framework che, dato il nome di un controllo, ce lo restituisce sotto forma di generico object. Facciamo il cast dell’oggetto restituito in un vero e proprio Control, dopodichè richiamiamo la funzione Focus che fa proprio quello che serve a noi: impostare il focus sul controllo, come se l’utente lo avesse selezionato. Il gioco è fatto!

Piccola curiosità: in molti esempi di codice che trovate in rete (e anche in uno dei tutorial ufficiali Microsoft, a dire la verità) il codice per recuperare l’ultimo controllo attivo e impostare il focus viene comunque gestito all’interno dell’evento OnNavigatedTo. Il fatto che, sull’emulatore, il codice non funzionasse veniva imputato ad un bug della versione beta. In realtà, come abbiamo visto, non si tratta affatto di un bug, ma di una errata comprensione degli eventi che scandiscono il ciclo di vita di una pagina. Un ringraziamento speciale a Corrado per avermi illuminato su questa cosa Smile

Come sempre, di seguito trovate il link per scaricare un progetto d’esempio che implementa quando abbiamo visto: oltre al codice già riportato in questo post, troverete implementato anche il codice per salvare in un tombstone il contenuto delle varie textbox.


Windows Phone , Tombstone

1 comments

Related Post


(will not be published)
(es: http://www.mysite.com)