Navigation entre deux fenêtres

Apr 22, 2013 at 6:56 PM
Bonjour,

J'utilise actuellement votre librairie (très pratique) sur un projet perso. Elle me permet de naviguer de UserControl en UserControl sur une même Window. Est-il possible de l'utiliser afin de naviguer d'une window vers une autre (par exemple : Fenêtre authentification ->Fenêtre Main) ? Si oui, de quelle manière ?

Cordialement,
Coordinator
Apr 22, 2013 at 7:11 PM
Bonsoir,
malheureusement pour le moment ce n’est pas prévu. La librairie est conçue pour une navigation type Windows 8 en mode mono-fenêtrée. En effet la vue associée à votre vue-modèle est affichée dans un ContentPresenter comme vous avez du le voir lors de la mise en place de la librairie.
Pouvez-vous modifier l’architecture de votre application pour afficher votre fenêtre d’authentification ?
Envoyé depuis Courrier Windows
De : JeanMarcP
Envoyé : ‎lundi‎ ‎22‎ ‎avril‎ ‎2013 ‎20‎:‎56
À : [email removed]

From: JeanMarcP

Bonjour,

J'utilise actuellement votre librairie (très pratique) sur un projet perso. Elle me permet de naviguer de UserControl en UserControl sur une même Window. Est-il possible de l'utiliser afin de naviguer d'une window vers une autre (par exemple : Fenêtre authentification ->Fenêtre Main) ? Si oui, de quelle manière ?

Cordialement,
Apr 22, 2013 at 7:18 PM
ok, alors la possibilité que j'ai est d'inclure par le biais d'un user contrôle l'authentification dans la même fenêtre. Par contre, si je souhaite conserver deux fenêtre comment puis-je naviguer facilement à travers l'autre fenêtre tout en respectant le pattern MVVM (je suis débutant, en cours d'apprentissage). Si j'ai bien compris, il faut que j'évite de faire ce genre de code dans le viewModel : MainWindow m = new MainWindow(); m.show();

Cordialement,
Coordinator
Apr 22, 2013 at 7:26 PM
Dans le ViewModel oui ile ne faut pas faire cela, mais il faut se dire que MVVM n’est pas un pattern au strict. Il ne faut pas penser que seul le code doit être inclus dans le ViewModel, concernant les interactions de type purement graphique vous pouvez passer par le code behind de votre vue. Une autre solution consiste à passer par le Messenger de MVVMLight en gérant le lancement de votre fenêtre par un RelayCommand.
Envoyé depuis Courrier Windows
De : JeanMarcP
Envoyé : ‎lundi‎ ‎22‎ ‎avril‎ ‎2013 ‎21‎:‎19
À : [email removed]

From: JeanMarcP

ok, alors la possibilité que j'ai est d'inclure par le biais d'un user contrôle l'authentification dans la même fenêtre. Par contre, si je souhaite conserver deux fenêtre comment puis-je naviguer facilement à travers l'autre fenêtre tout en respectant le pattern MVVM (je suis débutant, en cours d'apprentissage). Si j'ai bien compris, il faut que j'évite de faire ce genre de code dans le viewModel : MainWindow m = new MainWindow(); m.show();

Cordialement,
Apr 22, 2013 at 7:31 PM
Ok merci pour cette réponse je vais du coup essayer d'utiliser le Messenger de MVVMLight.

Cordialement,
Coordinator
Apr 22, 2013 at 7:35 PM
Le Messenger est une bonne solution pour ne pas “enfreindre” le principe du MVVMLight mais il faut faire attention de ne pas en abuser, il faut comprendre que le Messenger envoi un message et qu’une classe qui surveille ce message va le recevoir, mais le temps de communication sur ce système ne sera pas toujours le même, il faut donc faire attention a ne pas initialiser de traitement qui puisse dépendre de ce temps de communication mais cela reste une très bonne solution pour conserver le principe MVVMLight.
Envoyé depuis Courrier Windows
De : JeanMarcP
Envoyé : ‎lundi‎ ‎22‎ ‎avril‎ ‎2013 ‎21‎:‎31
À : [email removed]

From: JeanMarcP

Ok merci pour cette réponse je vais du coup essayer d'utiliser le Messenger de MVVMLight.

Cordialement,
Apr 23, 2013 at 9:52 AM
J'ai une dernière question sur ce sujet :
J'ai créé ma première fenêtre d'authentification qui dès la réception d'un message de son viewmodel lance la mainView
La mainView utilise la navigation NaveGar, ainsi le mainviewModel est instancié dans le constructeur du viewModelLocator. Le Hic, c'est que le viewModelLocator est instancié depuis la fenêtre d'authentification ce qui à pour conséquence l'instanciation du mainViewModel alors que la page affiché est la fenêtre d'authentification. Comment puis-je palier à ce problème ?

Code :
public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        // Enregistrer la classe de navigation dans l'IOC
        if (!SimpleIoc.Default.IsRegistered<INavigation>())
        {
            SimpleIoc.Default.Register<INavigation, Navigation>();
        }

        if (!SimpleIoc.Default.IsRegistered<AuthenticationViewModel>())
        {
            SimpleIoc.Default.Register<AuthenticationViewModel>();
        }

        if (!SimpleIoc.Default.IsRegistered<IMessageBoxService>())
        {
            SimpleIoc.Default.Register<IMessageBoxService, MessageBoxService>();
        }

        //Générer le viwemodel principal, le type du viewmodel peut être n'importe lequel
        //Cette génération va permettre de créer au de la navigation
        // une instance unique pour le viewmodel principal qui sera
        //utilisé par la classe navigation           
        NavigationService.GenerateMainViewModelInstance<MainViewModel>();
    }
Coordinator
Apr 23, 2013 at 9:57 AM
vous pouvez générer le MainViewModel au moment où vous le souhaitez, du moment que cela se fasse avant le premier appel à une navigation. Donc lorsque vous êtes prêt à appeler votre MainView vous faites simplement un SimpleIoc.Default.GetInstance<INavigation>.GenerateMainViewModelInstance<MainViewModel>();
Je vois dans votre code un NavigationService, c’est une instance de la navigation ?
Envoyé depuis Courrier Windows
De : JeanMarcP
Envoyé : ‎mardi‎ ‎23‎ ‎avril‎ ‎2013 ‎11‎:‎52
À : [email removed]

From: JeanMarcP

J'ai une dernière question sur ce sujet :
J'ai créé ma première fenêtre d'authentification qui dès la réception d'un message de son viewmodel lance la mainView
La mainView utilise la navigation NaveGar, ainsi le mainviewModel est instancié dans le constructeur du viewModelLocator. Le Hic, c'est que le viewModelLocator est instancié depuis la fenêtre d'authentification ce qui à pour conséquence l'instanciation du mainViewModel alors que la page affiché est la fenêtre d'authentification. Comment puis-je palier à ce problème ?

Code :
public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        // Enregistrer la classe de navigation dans l'IOC
        if (!SimpleIoc.Default.IsRegistered<INavigation>())
        {
            SimpleIoc.Default.Register<INavigation, Navigation>();
        }

        if (!SimpleIoc.Default.IsRegistered<AuthenticationViewModel>())
        {
            SimpleIoc.Default.Register<AuthenticationViewModel>();
        }

        if (!SimpleIoc.Default.IsRegistered<IMessageBoxService>())
        {
            SimpleIoc.Default.Register<IMessageBoxService, MessageBoxService>();
        }

        //Générer le viwemodel principal, le type du viewmodel peut être n'importe lequel
        //Cette génération va permettre de créer au de la navigation
        // une instance unique pour le viewmodel principal qui sera
        //utilisé par la classe navigation           
        NavigationService.GenerateMainViewModelInstance<MainViewModel>();
    }
Apr 23, 2013 at 10:01 AM
ok je vais tester...
Oui NavigationService est une instance de la navigation :

public static INavigation NavigationService
    {
        get
        {
            return SimpleIoc.Default.GetInstance<INavigation>();
        }
    }
Coordinator
Apr 23, 2013 at 10:05 AM
d’accord, très bien, j’avais eu “peur” que vous ayez fait un var NavigationService = new Navigation(); 😉
Envoyé depuis Courrier Windows
De : JeanMarcP
Envoyé : ‎mardi‎ ‎23‎ ‎avril‎ ‎2013 ‎12‎:‎01
À : [email removed]

From: JeanMarcP

ok je vais tester...
Oui NavigationService est une instance de la navigation :

public static INavigation NavigationService
    {
        get
        {
            return SimpleIoc.Default.GetInstance<INavigation>();
        }
    }
Apr 23, 2013 at 10:10 AM
lol, ok parfait cela fonctionne !
Par contre je me pose la question sur ce code, il y a t-il une manière plus propre d'éviter de naviguer vers une autre page trop tôt :

private readonly DispatcherTimer _timerLoadHome;
public MainViewModel()
    {
        BackCommand = new RelayCommand(BackToLastPage);
        //Permet d'éviter l'appel à la navigation pendant le chargement du viewmodel principal. Sans ceci le chargement du MainViewModel
        //ne se passe pas correctement puisque le chargement du viewmodel n'est pas possible
        _timerLoadHome = new DispatcherTimer
        {
            Interval = new TimeSpan(0, 0, 0, 0, 500)
        };
        _timerLoadHome.Tick += LoadHome;
        _timerLoadHome.Start();

    }
private void LoadHome(object sender, EventArgs e)
    {
        log.Info("Start");
        try
        {
            _timerLoadHome.Stop();
            //if (!IsInDesignMode)
            //{
            ViewModelLocator.NavigationService.NavigateTo<HomeViewModel>(null, "LoadPage", null);
            //}
        }
        catch (Exception ex)
        {
            log.Error("Error", ex);
            ViewModelLocator.MessageService.Show("Erreur lors du chargement de la page principale", "Erreur");
            PersonalManager.App.Current.Shutdown();
        }
        log.Info("End");
    }
Coordinator
Apr 23, 2013 at 11:13 AM
Tu peux (on peut se tutoyer je pense), pour eviter cela, faire dans ton MainView.xaml.cs (je te le note de tête, y a peut-être quelques petites fautes) :
public MainView()
{
    InitializeComponent();
    this.Loaded += MainViewLoaded;
}

public void MainViewLoaded(object sender, EventArgs e)
{
    SimpleIoc.Default.GetInstance<INavigation>.NavigateTo<HomeViewModel>(null, "LoadPage", null);
}
Cela devrait fonctionner je pense.
Apr 23, 2013 at 12:02 PM
oui génial cela fonctionne! Cependant est-ce que cette façon de faire est contraire au pattern MVVM car il y a une une intelligence dans le codebehind. Est-ce qu'il ne vaut pas mieux passer par le messenger mvvmLight ?
Coordinator
Apr 25, 2013 at 1:44 PM
Je te renvoi la réponse que je t'avais faite il y a 2 jours parce que je ne suis pas sur que tu l'ai eu :

Il n'y a aucune intelligence (en valeur ajoutée je parle) lors d'un lancement tel que celui-là, on parle d'éviter le code métier dans la Vue en MVVM, mais les interactions graphiques et ce genre d'actions peuvent parfaitement être réalisé dans le code-behind. Comme je te le disais précédemment, MVVM n'est pas un pattern au sens strict, c'est plus un guideline de programmation, rien ne sert de le suivre absolument à la lettre, car tu vas, pour certaines situations, construire une usine à gaz qui deviendra non maintenable par un autre que toi (ou même toi plusieurs mois plus tard) alors que parfois un code simple permet d'avoir quelque chose qui fonctionne aussi bien et qui est maintenable.

Il faut garder à l'esprit que même si toi tu trouves cela très propre, ton client ne verra que le résultat final et si la maintenabilité du code en devient insupportable, en terme de coût, juste pour avoir appliqué à la lettre un pattern à la mode, cela ne fait pas parti d'un bon travail. Un bon développeur maitrise non seulement son domaine de programmation, mais également des concepts comme la maintenabilité, la gestion des codes sources, l'expérience utilisateur, les coût raisonnables et sait donc quand il peut appliquer certaines règles. Si tu garde cela à l'esprit ca n'en sera que mieux.

Si tu veux continuer à discuter de l'archi de ton appli ou bien d'autre chose sur le dev., je te donne un email plutôt que de continuer dans la conversation sur CodePlex.

Utilise : kopigi at outlook.com