1.Introduction

Windows Phone 7 (WP7) est la nouvelle plateforme de développement de Microsoft destinée aux smartphones.

Cet article est le quatrième d'une série traitant du développement d'applications sous WP7.

Dans ce tutoriel nous allons voir comment naviguer entre les pages d'une application Silverlight pour Windows Phone 7. Nous verrons également que le bouton "Back" du téléphone s'interface parfaitement avec le framework de navigation de Silverlight pour WP7. Nous verrons enfin comment faire passer des informations entre les pages.

Si besoin, ou en guise d'introduction, n'hésitez pas à aller consulter les articles précédents :

2.La navigation au sein d'une application WP7

Les Windows Phones disposent d'un bouton "Back".

Image non disponible
Figure 1 : Le bouton Back.



Celui-ci, comme son nom le suggère, permet de revenir à la page précédente. Maîtriser la navigation entre les pages devient un besoin fondamental pour accompagner celle de l'utilisateur.

Silverlight dispose de plusieurs outils pour aider à la navigation entre les pages. C'est tout naturellement que Silverlight pour Windows Phone 7 fournit des moyens de navigation adaptés aux téléphones.

2.1.L'HyperlinkButton

Pour voir comment fonctionne la navigation, commençons par créer une application WP7 (Fichier -> Nouveau Projet -> Application Windows Phone).

Comme le Silverlight classique, Silverlight pour Windows Phone dispose d'un contrôle HyperlinkButton qui offre la possibilité de naviguer entre les pages. Ajoutons-en deux sur la page principale :

MainPage.xaml
Sélectionnez

<Grid x:Name="LayoutRoot" Background="Transparent">
	<Grid.RowDefinitions>
		<RowDefinition Height="Auto"/>
		<RowDefinition Height="*"/>
	</Grid.RowDefinitions>

	<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
		<TextBlock x:Name="PageTitle" Text="Démo Navigation" Margin="9,-7,0,0" FontSize="55" />
	</StackPanel>

	<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
		<StackPanel>
			<HyperlinkButton NavigateUri="/NavigationState.xaml" Content="Navigation State" />
			<HyperlinkButton NavigateUri="/NavigationQuery.xaml" Content="Navigation Query" />
		</StackPanel>
	</Grid>
</Grid>

On peut voir ici qu'il est très simple de faire un lien vers d'autres pages en utilisant l'attribut NavigateUri de l'HyperlinkButton.
Il suffit d'indiquer l'emplacement d'une page XAML.

Créons les deux pages NavigationState.xaml et NavigationQuery.xaml. Celles-ci seront identiques à part au niveau du titre qui nous permettra de les différencier. Puis lançons l'application (F5).

On peut voir que lorsqu'on clique sur "Navigation State", alors on change de page. Tout à fait naturellement, lorsque l'on souhaite revenir à la page précédente, on peut cliquer sur le bouton "Back" du téléphone. On peut faire de même avec le lien "Navigation Query".

Et voilà, nous naviguons entre les pages de notre application en n'ayant presque rien fait, à part ajouter un contrôle HyperlinkButton.


Modifions une des pages, par exemple NavigationState pour rajouter un bouton :

MainPage.xaml
Sélectionnez

<Button Content="Retour" Click="Button_Click" />

et traitons l'événement du clic sur le bouton côté code behind :

MainPage.xaml.cs
Sélectionnez

private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
	NavigationService.GoBack();
}

Comme on peut s'en douter, dans la mesure où c'est quand même assez explicite, en cliquant sur ce bouton, on revient à la page précédente, comme si on avait appuyé sur le bouton "Back".
La classe NavigationService contient toutes les méthodes qu'il faut pour gérer la navigation.

La classe NavigationService permet aussi de naviguer entre les pages par code, avec notamment sa fonction Navigate().

Illustrons ce comportement en créant sur la page NavigationState une ListBox où nous affectons la propriété ItemsSource à une liste d'articles.
Pour ce faire, créons un semblant de modèle via les classes suivantes :

Article.cs
Sélectionnez

public class Article
{
	public string Nom { get; set; }
	public DateTime DatePublication { get; set; }
	public string Contenu { get; set; }
}

et

Model.cs
Sélectionnez

public static class Model
{
	public static List<Article> GetArticles()
	{
		List<Article> articles = new List<Article>();
		articles.Add(new Article { 
			Nom = "Introduction WP7", DatePublication = new DateTime(2010, 11, 15), 
			Contenu = "Cet article constitue une introduction à WP7" });
		articles.Add(new Article { 
			Nom = "Listbox WP7", DatePublication = new DateTime(2010, 20, 11), 
			Contenu = "Cet article parle de la ListBox WP7 et de l'isolated storage" });
		articles.Add(new Article { 
			Nom = "Contrôle Pivot WP7", DatePublication = new DateTime(2010, 12, 5), 
			Contenu = "Cet article explore le contrôle Pivot" });
		articles.Add(new Article { 
			Nom = "Navigation WP7", DatePublication = new DateTime(2010, 12, 30), 
			Contenu = "Cet article permet de découvrir la navigation WP7" });
		return articles;
	}
}

Ici, on construit simplement une liste très sommaire d'articles.

2.3.1.Utiliser le dictionnaire d'état pour faire transiter des informations

La page NavigationState.xaml contiendra :

NavigationState.xaml
Sélectionnez

<Grid x:Name="LayoutRoot" Background="Transparent">
	<Grid.RowDefinitions>
		<RowDefinition Height="Auto"/>
		<RowDefinition Height="*"/>
	</Grid.RowDefinitions>

	<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
		<TextBlock x:Name="PageTitle" Text="Navigation State" Margin="9,-7,0,0" FontSize="55" />
	</StackPanel>

	<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
		<ListBox x:Name="listBox" SelectionChanged="listBox_SelectionChanged">
			<ListBox.ItemTemplate>
				<DataTemplate>
					<Border CornerRadius="10" Margin="50 30 30 30" 
						Background="Gray" Width="300" Height="100">
						<TextBlock Text="{Binding Nom}" VerticalAlignment="Center" 
							HorizontalAlignment="Center" />
					</Border>
				</DataTemplate>
			</ListBox.ItemTemplate>
		</ListBox>
	</Grid>
</Grid>

et dans le code behind nous aurons :

NavigationState.xaml.cs
Sélectionnez

public partial class NavigationState : PhoneApplicationPage
{
	private ObservableCollection<Article> articles;

	public NavigationState()
	{
		InitializeComponent();

		articles = new ObservableCollection<Article>();
		foreach (Article article in Model.GetArticles())
		{
			articles.Add(article);
		}

		listBox.ItemsSource = articles;
	}

	private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
	{
		Article currentArticle = (Article)listBox.SelectedItem;
		PhoneApplicationService.Current.State["Article"] = currentArticle;
		NavigationService.Navigate(new Uri("/ArticleView.xaml", UriKind.Relative));
	}
}

On construit une ObservableCollection avec la liste d'articles que l'on affecte à la propriété ItemsSource de la ListBox.
Dans l'événement de changement de sélection de la ListBox, nous récupérons l'élément sélectionné et le stockons dans le dictionnaire d'état de l'application. Puis nous appelons le service de navigation en lui communiquant l'URL de la page à afficher.

Comme vous l'aurez compris, nous utilisons le dictionnaire d'état de l'application pour communiquer un contexte à la page vers laquelle nous allons naviguer. C'est une solution, sachant qu'il y en a d'autres dont une que nous allons explorer plus loin.

Créons désormais la page ArticleView.xaml avec le xaml suivant :

ArticleView.xaml
Sélectionnez

<Grid x:Name="LayoutRoot" Background="Transparent">
	<Grid.RowDefinitions>
		<RowDefinition Height="Auto"/>
		<RowDefinition Height="*"/>
	</Grid.RowDefinitions>

	<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
		<TextBlock x:Name="ApplicationTitle" Text="Consultation d'article :" 
			Style="{StaticResource PhoneTextNormalStyle}"/>
		<TextBlock x:Name="PageTitle" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
	</StackPanel>

	<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
		<StackPanel>
			<TextBlock x:Name="date" />
			<TextBlock x:Name="contenu" />
		</StackPanel>
	</Grid>
</Grid>

Pour récupérer le contexte, nous allons surcharger la méthode OnNavigatedTo. C'est la méthode qui est appelée lorsque l'on navigue sur une page.

ArticleView.xaml.cs
Sélectionnez

protected override void OnNavigatedTo(NavigationEventArgs e)
{
	Article currentArticle = (Article)PhoneApplicationService.Current.State["Article"];

	PageTitle.Text = currentArticle.Nom;
	date.Text = currentArticle.DatePublication.ToShortDateString();
	contenu.Text = currentArticle.Contenu;
	base.OnNavigatedTo(e);
}

Nous récupérons la sélection depuis le dictionnaire d'état et affichons le contenu dans la page.

2.3.2.Utilisation de la query string

Une autre façon de faire est d'utiliser la query string.

Pour illustrer ce fonctionnement, modifions la page NavigationQuery.xaml qui est quasiment la même que la page NavigationState.xaml au détail près que le titre est différent et que la méthode listBox_SelectionChanged du code behind sera :

NavigationQuery.xaml.cs
Sélectionnez

private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
	NavigationService.Navigate(new Uri("/ArticleView2.xaml?index=" + listBox.SelectedIndex, UriKind.Relative));
}

Ici, on utilise la query string pour passer la valeur de l'index de l'élément sélectionné.

La page ArticleView2.xaml est exactement la même que ArticleView.xaml à la différence près que l'on récupère les informations différemment, depuis la méthode OnNavigatedTo :

ArticleView2.xaml.cs
Sélectionnez

protected override void OnNavigatedTo(NavigationEventArgs e)
{
	string indexStr;
	if (NavigationContext.QueryString.TryGetValue("index", out indexStr))
	{
		int index = int.Parse(indexStr);
		Article currentArticle = Model.GetArticles()[index];
		PageTitle.Text = currentArticle.Nom;
		date.Text = currentArticle.DatePublication.ToShortDateString();
		contenu.Text = currentArticle.Contenu;
	}
	base.OnNavigatedTo(e);
}

Ici on utilise le contexte de navigation (NavigationContext) pour récupérer la valeur que nous avons transmise dans la query string.
Une fois cette valeur récupérée, il ne reste plus qu'à accéder à l'élément de la liste à l'index adéquat et nous pouvons afficher notre contenu.

Nous avons pu voir ainsi deux façons différentes de naviguer entre les pages, via le contrôle HyperlinkButton et via le NavigationService. Puis nous avons vu deux façons différentes de passer des informations entre les pages, via la query string et via le dictionnaire d'état de l'application.

3.Démonstration de l'application

Pour se rendre compte de la navigation, regardons cette vidéo :



Dans un premier temps, je clique sur un HyperLinkButton et je change de page.
Je clique sur "Back" et je reviens à la page précédente.
Je peux cliquer sur un élément de la ListBox et je suis redirigé vers une autre page où je peux voir le contenu d'un article.
Encore une fois, un clic sur le bouton "Back" permet de revenir à la page précédente.
Cliquons encore une fois sur le bouton "Back" et nous pouvons observer que l'application WP7 gère bien la pile de navigation.

4.Téléchargements

Vous pouvez télécharger ici les sources du projet : version rar (91 Ko), version zip (100 Ko).

5.Conclusion

Nous avons donc vu dans ce tutoriel comment créer une application Windows Phone 7 qui tire parti du framework de navigation Silverlight adapté à WP7.
Nous avons dans un premier temps utilisé le contrôle HyperLinkButton. Puis nous avons utilisé la classe NavigationService pour naviguer en arrière et naviguer vers une autre page. Enfin, nous avons vu comment faire passer des informations entre les pages via le dictionnaire d'état et par la query string.

J'espère que ce tutoriel a pu vous être utile et vous a donné envie de vous perfectionner dans la création d'applications pour Windows Phone 7.

Remerciements

Je remercie les membres de l'équipe Dotnet pour leurs relectures attentives du document et leurs remarques ainsi que ClaudeLELOUP pour sa relecture orthographique.

Contact

Si vous constatez une erreur dans le tutoriel, dans le code source, dans la programmation ou pour toute information, n'hésitez pas à me contacter par le forum.