简体   繁体   中英

Prism Navigation in Xamarin Forms

I am developing a Xamarin Forms app, which it uses Prism Forms for navigation, basing me in some guides like: bootstrap-series-xamarin-forms-in-prism-forms

The problem is that by pressing the buttons on the ListView in ShellMaster, which is used for browsing, nothing happens, and the debugger does not register any breakpoint of the Navigate method.

My Code:

App.xaml.cs

using Xamarin.Forms.Xaml;
using Prism.Unity;
using Prism.Ioc;
using Prism;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace MyNewApp
{
    public partial class App : PrismApplication
    {
        public App(IPlatformInitializer initializer = null) : base(initializer) { }

        protected async override void OnInitialized()
        {
            InitializeComponent();

            await NavigationService.NavigateAsync(nameof(Views.Shell) + "/" + nameof(Views.AppShellNavigationPage) + "/" + nameof(Views.Pages.HomePage));
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // Register Shell
            containerRegistry.RegisterForNavigation<Views.Shell>(nameof(Views.Shell));

            // Register Navigation page
            containerRegistry.RegisterForNavigation<Views.AppShellNavigationPage>(nameof(Views.AppShellNavigationPage));

            // Register Pages
            containerRegistry.RegisterForNavigation<Views.Pages.HomePage>(nameof(Views.Pages.HomePage));
            containerRegistry.RegisterForNavigation<Views.Pages.PageA>(nameof(Views.Pages.PageA));
            containerRegistry.RegisterForNavigation<Views.Pages.PageB>(nameof(Views.Pages.PageB));
            containerRegistry.RegisterForNavigation<Views.Pages.PageC>(nameof(Views.Pages.PageC));
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

Shell.xaml

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyNewApp.Views.Shell"
             xmlns:pages="clr-namespace:MyNewApp.Views">
  <MasterDetailPage.Master>
    <pages:ShellMaster x:Name="MasterPage" />
  </MasterDetailPage.Master>
    <MasterDetailPage.Detail/>
</MasterDetailPage>

Shell.xaml.cs

using Xamarin.Forms.Xaml;
using Prism.Navigation;
using Xamarin.Forms;

namespace MyNewApp.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Shell : MasterDetailPage
    {
        public Shell()
        {
            InitializeComponent();

            MasterBehavior = MasterBehavior.Popover;
        }
    }

    public class AppShellNavigationPage : NavigationPage, INavigationPageOptions, IDestructible
    {
        public AppShellNavigationPage()
        {
            BarTextColor = Color.White;

            BarBackgroundColor = Color.Accent;
        }

        public bool ClearNavigationStackOnNavigation
        {
            get { return false; }
        }

        public void Destroy()
        {

        }
    }
}

ShellMaster.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyNewApp.Views.ShellMaster"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             Title="Master">
    <StackLayout>
        <ListView x:Name="MenuItemsListView"
              SeparatorVisibility="None"
              HasUnevenRows="true"
              ItemsSource="{Binding MenuItems}"
              SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
              >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal" Padding="15,10" HorizontalOptions="FillAndExpand">
                            <Label VerticalOptions="FillAndExpand" VerticalTextAlignment="Center" Text="{Binding Title}"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

ShellMasterViewModel.cs

using System.Collections.ObjectModel;
using System.Collections.Generic;
using Prism.Navigation;
using MyNewApp.Models;
using Prism.Commands;
using Prism.Mvvm;

namespace MyNewApp.ViewModels
{
    public class ShellMasterViewModel : BindableBase, INavigationAware
    {
        protected INavigationService _navigationService { get; }
        public ObservableCollection<NavigationItem> MenuItems { get; set; }

        private NavigationItem _selectedItem;
        public NavigationItem SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                SetProperty(ref _selectedItem, value);

                if (_selectedItem == null)
                {
                    return;
                }

                _navigationService.NavigateAsync(nameof(Views.Shell) + "/" + nameof(Views.AppShellNavigationPage) + "/" + nameof(Views.Pages.NoActiveProject));                

            }
        }

        public DelegateCommand<NavigationItem> SelectItemCommand { get; set; }

        public ShellMasterViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;

            MenuItems = new ObservableCollection<NavigationItem>()
            {
                new NavigationItem { Title="HomePage", PageName = nameof(Views.Pages.HomePage)},
                new NavigationItem { Title="PageA", PageName = nameof(Views.Pages.PageA)},
                new NavigationItem { Title="PageB", PageName = nameof(Views.Pages.PageB)},
                new NavigationItem { Title="PageC", PageName = nameof(Views.Pages.PageC)},
            };

            SelectItemCommand = new DelegateCommand<NavigationItem>((s) => Navigate(s));
        }

        public async void Navigate(NavigationItem selectedItem)
        {
            if (selectedItem != null)
            {
                await _navigationService.NavigateAsync(nameof(Views.Shell) + "/" + nameof(Views.AppShellNavigationPage) + "/" + selectedItem.PageName);
            }
        }

        List<string> ModulePages()
        {
            return new List<string>()
            {
                nameof(Views.Pages.HomePage),
                nameof(Views.Pages.PageA),
                nameof(Views.Pages.PageB),
                nameof(Views.Pages.PageC),
            };
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }
    }
}

NavigationItem.cs

namespace MyNewApp.Models
{
    public class NavigationItem
    {
        public string Title { get; set; }

        public string Icon { get; set; }

        public string PageName { get; set; }
    }
}

What I want to achieve is to be able to navigate with the elements of the ListView and that by pressing them and the itemsSelected does not turn null so that they remain selected.

Appreciate your help.

Not easy do dissect your sample, but I'm guessing your Navigate(NavigationItem selectedItem) is not correct. It should trigger a single navigation, so that PRISM can load the selected page into the detail part of the MasterDetail setup.

Try with : await _navigationService.NavigateAsync( nameof(Views.AppShellNavigationPage) + "/" + selectedItem.PageName);

For reference I once setup the same scenario in a test repo on my own GitHub, maybe that can help even further? https://github.com/Depechie/PRISMNavigation/blob/master/BasePageDemo.NetStandard/ViewModels/MDViewModel.cs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM