On parle Windows, C#, Apple, Android, Js, …

MvvmLight 5.0 et la navigation

Nouveautés

Une grande nouveauté de MVVMLight5 est l’apparition du INavigationService.

Le INavigationService est un Pattern permettant la navigation dans l’application sans utiliser la couche visuelle. Il est alors possible de migrer le même code sous différentes plateformes sans les particularités de la navigation.

Il sera également possible de tester les actions de navigation grâce aux tests unitaires automatisés.

Navigation entre les pages

Un petit rappel des différentes implémentations de la navigation entre les pages d’une application.

Sans MVVM et sans INavigationService

Dans une application standard (non MVVM), le passage d’une page à l’autre va se faire de la façon suivante. Sur le click du bouton, on appelle la page concernée.

En Xaml :

<Button Content="Go to Page 2" 
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                Click="Button_Click"/>

En Code Behind (Ici dans une application Windows 8.x / Windows Phone 8 Xaml)

private void Button_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(Page2));
}

 

En MVVM sans implémentation de l’évènement « Click »

Afin de ne pas coder les actions dans l’interface visuelle, nous allons passer par des ICommand.

MVVM Light possède déjà les mécanismes pour utiliser les actions avec des RelayCommand.

Nous utilisons une classe MainViewModel où nous allons coder l’action.

public class MainViewModel
{
    public ICommand NavigatePage2Command { get; private set; }
    public MainViewModel()
    {
        NavigatePage2Command = new RelayCommand(()=>
        {
	// Code to Execute
        });
    }
}

Cette classe est ensuite associée dans le XAML au niveau de la définition de la Page.

DataContext="{Binding Source={StaticResource Locator}, Path=MainViewModel}"

Le Bouton est alors codé de cette façon. L’action « Command » remplace l’évènement « Click » : Le bouton utilise le Binding pour associer l’évènement à l’action.

<Button 
  VerticalAlignment="Center" 
  HorizontalAlignment="Center"
  Content="Page 2"
  Command="{Binding NavigatePage2Command}"
/>

Les problèmes de la navigation.

Premier problème : L’indépendance de la Vue

La command se trouve dans le ViewModel. L’objet Frame qui est un objet visuel n’est pas accessible sauf à ajouter un espace de nommage lié à la vue pour pouvoir le manipuler. En faisant cela on « casse » le pattern ViewModel.

Deuxième problème : Le codage spécifique

L’objet Frame est spécifique aux applications Windows 8 et Universal Apps. Si vous souhaitez porter ce code en WPF ou Windows Phone 8.0 , 8.1 version Silverlight ou Xamarin Android / iPhone, la syntaxe sera différente.

Ce qui se fait de plus courant, est l’implémentation d’une interface souvent appelée INavigationService et de sa classe associée NavigationService.

INavigationService va contenir les éléments de navigation, souvent des méthodes NavigateToPage1, GoBack(),… et son implémentation (NavigationService) va coder les méthodes de navigation propre à chaque plateforme.

Depuis quelques semaines, MVVM Light 5, fournit tout ce mécanisme « in the Box ».

INavigationService du MVVM Light 5.0

Etape 1 : Définition du Service dans ViewModelLocator.

Le ViewModelLocator sert à initialiser tous les services et enregistrer tous les ViewModel consultés dans les vues.

On va ajouter la ligne suivante dans son constructeur :

SimpleIoc.Default.Register<INavigationService>(() => CreateNavigationService());

ce qui donne :

static ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    SimpleIoc.Default.Register<INavigationService>(() => CreateNavigationService());
...            
    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register<Page2ViewModel>();
}

CreateNavigationService() va contenir un référentiel sous forme de configuration de chaque page :

private static INavigationService CreateNavigationService()
{
    var navigationService = new NavigationService();
    navigationService.Configure("Page2", typeof(Page2));
    return navigationService;
}

 

Si vous avez plusieurs pages sur lesquelles vous voulez naviguer il faudra les définir à cet endroit avec la méthode Configure.

Le référencement de ces pages s’effectue par une « string » ce qui peut être source d’erreur. Je vous recommande de passer par la définition de constantes pour bénéficier de l’IntelliSense et également éviter toute confusion.

public const string NavigationPage2 = "Page2";

Etape 2 : Navigation vers une page

Nous allons voir maintenant comment appeler une page dans le ViewModel.

Sur le RelayCommand (associé au bouton dans le XAML), l’appel va se faire de la façon suivante :

NavigatePage2Command = new RelayCommand(()=>
    {
        INavigationService navigationService = SimpleIoc.Default.GetInstance<INavigationService>();
        navigationService.NavigateTo(ViewModelLocator.NavigationPage2);
    });

Etape 3 (Optionnelle) : Retour vers la page précédente

On associe une action sur le Command (NavigateBackCommand dans cet exemple). L’action est associée au bouton retour, dans cette action, on utilise la méthode GoBack(). Cette instruction provient directement de MVVMLight 5, il n’y a rien de plus à faire.

public ICommand NavigateBackCommand { get; private set; }

public Page2ViewModel()
{
    NavigateBackCommand = new RelayCommand(() =>
    {
        INavigationService navigationService = SimpleIoc.Default.GetInstance<INavigationService>();
        navigationService.GoBack();
    });
}

Conclusion

MVVMLight dans sa version 5.0 simplifie de nouveau un peu plus le pattern M-V-VM en proposant les implémentations de navigation courantes directement dans ce Framework.

Avec une version « Portable », il est possible de créer un code très propre et indépendant d’une plateforme très facilement.

Le code est ici

Téléchargement du Code

Laissez un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.