Per prima cosa, in Visual Studio 2012 creiamo un nuovo progetto Windows 8. Nella finestra di dialog, selezioniamo Windows Store per accedere all'elenco dei template proposti da Visual Studio per applicazioni Windows 8. Scegli Blank App (XAML) come template, assegna al progetto il nome che preferisci e seleziona la directory su disco dove salvare la soluzione:
Prima di proseguire oltre, popoliamo la nostra applicazione con alcuni di dati d'esempio su cui effettuare semplici ricerche. In questo esempio non avremo nessuna pretesa grafica né tantomeno utilizzeremo pattern architetturali per rimanere sul pezzo.
Aggiungiamo al progetto una nuova classe, denominata Bike
, che rappresenti, poniamo, alcuni modelli di mountain bike (passatempo assai diffuso qui in Toscana), e una classe Biz
il cui unico metodo, GetAllBikes()
, restituisca una collezione di... biciclette, appunto. Questo che segue è il relativo codice:
public List GetAllBikes()
{
return new List()
{
new Bike() { BikeName = "Specialized Stumpjumper" },
new Bike() { BikeName = "Scott Spark" },
new Bike() { BikeName = "Kona Abra Cadabra" },
new Bike() { BikeName = "Cannondale Jekill" },
new Bike() { BikeName = "Rocky Mountain Altitude" },
new Bike() { BikeName = "Bianchi Metanol" },
new Bike() { BikeName = "Santacruz Tallboy" },
new Bike() { BikeName = "Canyon Torque" }
};
}
Agganciamo adesso i dati alla MainPage
della nostra applicazione. Per prima cosa, modifichiamo la pagina XAML aggiungendo un controllo ListView per mostrare l'elenco delle nostre entità (evidenziato in grassetto nel listato seguente):
<Page
x:Class="Html.it.Demo.SearchContractSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Html.it.Demo.SearchContractSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ListView x:Name="list" DisplayMemberPath="BikeName" />
</Grid>
</Page>
Nel code behind (MainPage.xaml.cs
) mettiamo in binding il controllo appena creato con la nostra lista di biciclette (le linee da aggiungere sono evidenziate in grassetto):
public MainPage()
{
this.InitializeComponent();
var biz = new Biz();
list.ItemsSource = biz.GetAllBikes();
}
Se eseguiamo la nostra applicazione premendo F5, ecco quello che otteniamo:
Ora che abbiamo qualche dato con cui verificare gli esempi, per implementare la funzionalità di search occorre dichiarare la relativa funzionalità nell'application manifest della nostra applicazione.
Per farlo, è sufficiente aprire il file Package.appxmanifest
all'interno del nostro progetto e, nel tab Declarations, selezionare la funzionalità di Search tra le opzioni disponibili all'interno della dropdown list denominata Available Declarations.
Così facendo, abbiamo registrato la nostra applicazione come search provider, ovvero come applicazione in grado di rispondere in qualunque momento alle ricerche effettuate dall'utente, fornendo i contenuti che la app stessa gestisce.
Per vedere che cosa è successo a seguito della registrazione, cliccate con il tasto destro sul progetto e selezionate Deploy per installare l'applicazione sul PC. Tornate alla Start Page di Windows 8 (tasto Windows), attivate la Charms Bar (premete Windows+C
oppure spostate il mouse nell'angolo in basso a destra dello schermo) e selezionate il charm Search. La nuova applicazione appare adesso nell'elenco delle applicazioni in cui poter effettuare ricerche:
Dal momento che non abbiamo ancora implementato il contratto di search, se provassimo a cliccare sulla nostra applicazione e a inserire un testo da cercare, non otterremmo alcun risultato.
Il secondo passo da compiere è dunque quello di implementare il contratto. Per questo è sufficiente aggiungere un nuovo Search Contract al nostro progetto (composto da una pagina XAML e dal relativo code behind).
Visual Studio vi chiederà se importare automaticamente una serie di file (classi helper, converter, collezioni di stile, etc.) funzionali alla corretta implementazione del contratto. Premete OK per confermare. L'aggiunta del contratto da Visual Studio inserisce automaticamente la declaration nel manifest che abbiamo visto prima.
Ecco come appare il contenuto del progetto al termine della nostra operazione:
Oltre a creare la pagina in cui verranno mostrati i risultati della ricerca (di default, SearchResultPage1.xaml
) e ad aggiungere i file necessari, Visual Studio modifica anche la classe App.cs
aggiungendovi l'handler (asincrono, come si può notare) incaricato di gestire l'evento di attivazione della ricerca da parte dell'utente. Il codice del metodo è riportato qui di seguito:
protected async override void OnSearchActivated(Windows.ApplicationModel.Activation.SearchActivatedEventArgs args)
{
// TODO: Register the Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted
// event in OnWindowCreated to speed up searches once the application is already running
// If the Window isn't already using Frame navigation, insert our own Frame
var previousContent = Window.Current.Content;
var frame = previousContent as Frame;
// If the app does not contain a top-level frame, it is possible that this
// is the initial launch of the app. Typically this method and OnLaunched
// in App.xaml.cs can call a common method.
if (frame == null)
{
// Create a Frame to act as the navigation context and associate it with
// a SuspensionManager key
frame = new Frame();
Html.Demo.SearchContract.Common.SuspensionManager.RegisterFrame(frame, "AppFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Restore the saved session state only when appropriate
try
{
await Html.Demo.SearchContract.Common.SuspensionManager.RestoreAsync();
}
catch (Html.Demo.SearchContract.Common.SuspensionManagerException)
{
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
}
frame.Navigate(typeof(SearchResultsPage1), args.QueryText);
Window.Current.Content = frame;
// Ensure the current window is active
Window.Current.Activate();
}
Come si vede, il metodo riceve come parametro un oggetto di tipo SearchActivatedEventArgs
. È proprio all'interno di questo oggetto che viene passata la stringa di ricerca digitata (query string) dall'utente nella relativa maschera.
Senza addentrarci troppo nei dettagli di funzionamento del metodo (che, in buona sostanza, controlla se l'applicazione era in esecuzione o meno per ripristinarne lo stato o creare il frame di contenuti da zero), è interessante osservare come la query string digitata dall'utente (ed evidenziata in grassetto nel listato sopra riportato) venga poi passata come parametro alla pagina di ricerca per poter essere gestita nel modo più appropriato e per mostrare il risultato a video.
Vediamo di ricapitolare quanto accaduto finora: l'utente ha attivato il charm di Search e ha digitato del testo da ricercare all'interno della nostra applicazione. L'evento di attivazione della ricerca è stato intercettato dal metodo OnSearchActivated
della nostra classe App
, il quale ha anche provveduto a spostare il frame principale dell'applicazione sulla pagina di ricerca (SearchResultPage1.xaml
, nel nostro esempio), passando il criterio di ricerca ricevuto (args) e ad attivarla (Window.Current.Activate()
) in modo da mostrare all'utente i risultati dell'operazione.