1

I'm using Windows Template Studio (Prism) to create a test project, but from the documentation, I'm unable to figure out navigation. I now know how to do it with MVVM Light, but had to ask, because documentation doesn't detail it. How do I navigate from page to page in Prism Windows Template Studio?

Works for MVVM Light:

ViewModelLocator.Current.NavigationService.Navigate(typeof(MyViewModel).FullName, null)

Works on Template10:

BootStrapper.Current.NavigationService.Navigate(typeof(MyViewPage), null)

Carlo Mendoza
  • 765
  • 6
  • 24

1 Answers1

2

You could create test app with Windows Template Studio and check Navigation Page project type then check prism Design pattern. You will find the _navigationService in the ShellViewModel class.

Works on Windows Template Studio Prism

_navigationService.Navigate(pageKey, null);

ShellViewModel.cs

public class ShellViewModel : ViewModelBase
{
    private static INavigationService _navigationService;
    private WinUI.NavigationView _navigationView;
    private bool _isBackEnabled;
    private WinUI.NavigationViewItem _selected;

    public ICommand ItemInvokedCommand { get; }

    public bool IsBackEnabled
    {
        get { return _isBackEnabled; }
        set { SetProperty(ref _isBackEnabled, value); }
    }

    public WinUI.NavigationViewItem Selected
    {
        get { return _selected; }
        set { SetProperty(ref _selected, value); }
    }

    public ShellViewModel(INavigationService navigationServiceInstance)
    {
        _navigationService = navigationServiceInstance;
        ItemInvokedCommand = new DelegateCommand<WinUI.NavigationViewItemInvokedEventArgs>(OnItemInvoked);
    }

    public void Initialize(Frame frame, WinUI.NavigationView navigationView)
    {
        _navigationView = navigationView;
        frame.NavigationFailed += (sender, e) =>
        {
            throw e.Exception;
        };
        frame.Navigated += Frame_Navigated;
        _navigationView.BackRequested += OnBackRequested;
    }

    private void OnItemInvoked(WinUI.NavigationViewItemInvokedEventArgs args)
    {
        var item = _navigationView.MenuItems
                        .OfType<WinUI.NavigationViewItem>()
                        .First(menuItem => (string)menuItem.Content == (string)args.InvokedItem);
        var pageKey = item.GetValue(NavHelper.NavigateToProperty) as string;
        _navigationService.Navigate(pageKey, null);


    }

    private void Frame_Navigated(object sender, NavigationEventArgs e)
    {
        IsBackEnabled = _navigationService.CanGoBack();
        Selected = _navigationView.MenuItems
                        .OfType<WinUI.NavigationViewItem>()
                        .FirstOrDefault(menuItem => IsMenuItemForPageType(menuItem, e.SourcePageType));
    }

    private void OnBackRequested(WinUI.NavigationView sender, WinUI.NavigationViewBackRequestedEventArgs args)
    {
        _navigationService.GoBack();
    }

    private bool IsMenuItemForPageType(WinUI.NavigationViewItem menuItem, Type sourcePageType)
    {
        var sourcePageKey = sourcePageType.Name;
        sourcePageKey = sourcePageKey.Substring(0, sourcePageKey.Length - 4);
        var pageKey = menuItem.GetValue(NavHelper.NavigateToProperty) as string;
        return pageKey == sourcePageKey;
    }
}

_navigationService comes from ShellViewModel construct method. And this instance was created in the App class.

protected override UIElement CreateShell(Frame rootFrame)
{
    var shell = Container.Resolve<ShellPage>();
    shell.SetRootFrame(rootFrame);
    return shell;
}
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • So to allow `_navigationService.Navigate(pageKey, null);` accessibility on other pages, I need to set `_navigationService` to `public` on `ShellViewModel`? I just tried it and does work, but is there a reason, why I shouldn't do it like that? – Carlo Mendoza Feb 22 '19 at 15:37
  • 1
    You have no need set _navigationService to public, you could get navigationServiceInstance in each view model construct method. For example `public Blank1ViewModel(INavigationService navigationServiceInstance) { _navigationService = navigationServiceInstance; }` – Nico Zhu Feb 23 '19 at 06:11
  • How about for `App.xaml.cs`? What would be considered good practice when navigating page to page there? – Carlo Mendoza Feb 23 '19 at 07:16
  • You could refer Tempate 10 Prism. I think it is good practice to share navigationService with BootStrapper. – Nico Zhu Feb 23 '19 at 07:23
  • Not sure I understand that last comment, unfortunately, but you've been a great help! – Carlo Mendoza Feb 23 '19 at 07:37
  • 1
    You are welcome, I think you could also store `navigationService` in the app.xaml.cs just like template 10 `BootStrapper` class. if the answer is helpful please consider accept it. thx. – Nico Zhu Feb 23 '19 at 07:45