Xamarin形式的棱镜导航

时间:2018-06-21 03:19:34

标签: c# xamarin xamarin.forms navigation prism

我正在开发Xamarin Forms应用程序,该应用程序使用Prism Forms进行导航,并基于以下一些指南进行操作: bootstrap-series-xamarin-forms-in-prism-forms

问题在于,通过按下ShellMaster中用于浏览的ListView上的按钮,什么也不会发生,并且调试器不会注册Navigate方法的任何断点。

我的代码:

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; }
    }
}

我想要实现的是能够导航ListView的元素,并且通过按下它们,itemsSelected不会变为null以便保持选中状态。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

不容易剖析您的样本,但我猜您的Navigate(NavigationItem selectedItem)不正确。 它应该触发一次导航,以便PRISM可以将所选页面加载到MasterDetail设置的详细信息部分。

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

作为参考,我曾经在自己的GitHub上的测试仓库中设置了相同的场景,也许可以进一步帮助您? https://github.com/Depechie/PRISMNavigation/blob/master/BasePageDemo.NetStandard/ViewModels/MDViewModel.cs