Alternative way to create shell in Prism.Windows 7.1.0?

陌路散爱 提交于 2019-12-13 03:26:29

问题


As of this writing, the upcoming Prism.Windows 7.1.0 from MyGet Package is missing override method CreateShell() and I really wonder if it's gonna be moved into another method or it'll be gone in the final release.

If so, what's the alternative solution to implement shell view, assuming the code is from this tutorial and DryIoC container is used instead.


回答1:


Rather than using the CreateShell() override, you could create the NavigationService inside of a NavigationView. The code provided in this answer is adapted from one of the three Template10 Samples, which, at the time of writing, has not been migrated over to the Prism Samples: Sample Project (16299). It should be noted that this answer uses Prism.Unity.Windows, however I would imagine that this can easily be swapped for Prism.DryIoc.Windows, or indeed any other supported framework, without causing issues.

App.xaml

<prism:PrismApplication
    x:Class="StudentRecords.Uwp.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:prism="using:Prism.Unity">

</prism:PrismApplication>

App.xaml.cs

using System.Threading.Tasks;
using Prism;
using Prism.Ioc;
using Prism.Unity;
using StudentRecords.Repositories;
using StudentRecords.Services;
using StudentRecords.Uwp.ViewModels;
using StudentRecords.Uwp.Pages;
using Windows.UI.Xaml;

namespace StudentRecords.Uwp
{
    sealed partial class App : PrismApplication
    {
        public App() => InitializeComponent();

        public override void RegisterTypes(IContainerRegistry container)
        {
            container.RegisterSingleton<AppShell, AppShell>();

            container.RegisterSingleton<IStudentService, StudentService>();

            container.RegisterSingleton<IStudentRepository, MockStudentRepository>();

            container.RegisterForNavigation<HomePage, HomePageViewModel>("Home");
            container.RegisterForNavigation<LecturersPage, LecturersPageViewModel>("Lecturers");
            container.RegisterForNavigation<SettingsPage, SettingsPageViewModel>("Settings");
            container.RegisterForNavigation<StudentsPage, StudentsPageViewModel>("Students");
        }

        public override void OnInitialized() { }

        public override async Task OnStartAsync(StartArgs args)
        {
            var appShell = Container.Resolve<AppShell>();
            Window.Current.Content = appShell;

            await appShell.NavigationView.InitializeAsync();
            var navigationService = appShell.NavigationView.NavigationService;
        }
    }
}

AppShell.xaml

<Page
    x:Class="StudentRecords.Uwp.AppShell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:StudentRecords.Uwp.Views"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <controls:PrismNavigationView x:FieldModifier="public" x:Name="NavigationView">
        <NavigationView.MenuItems>
            <NavigationViewItem controls:PrismNavigationViewProperties.NavigationUri="/Home" controls:PrismNavigationViewProperties.IsStartPage="True" Content="Home">
                <NavigationViewItem.Icon>
                    <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE80F;" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>

            <NavigationViewItemSeparator />

            <NavigationViewItem controls:PrismNavigationViewProperties.NavigationUri="/Students" Content="Students">
                <NavigationViewItem.Icon>
                    <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE716;" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>

            <NavigationViewItem controls:PrismNavigationViewProperties.NavigationUri="/Lecturers" Content="Lecturers">
                <NavigationViewItem.Icon>
                    <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE7BE;" />
                </NavigationViewItem.Icon>
            </NavigationViewItem>
        </NavigationView.MenuItems>
    </controls:PrismNavigationView>
</Page>

AppShell.xaml.cs

using Windows.UI.Xaml.Controls;

namespace StudentRecords.Uwp
{
    public sealed partial class AppShell : Page
    {
        public AppShell() => InitializeComponent();
    }
}

PrismNavigationView.cs

using Prism.Navigation;
using Prism.Services;
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace StudentRecords.Uwp.Views
{
    public class PrismNavigationView : NavigationView
    {
        public event EventHandler SettingsInvoked;

        public PrismNavigationView()
        {
            Content = ContentFrame = new Frame();

            ContentFrame.Navigated += ContentFrame_NavigatedAsync;

            NavigationService = Prism.Navigation.NavigationService.Create(ContentFrame, Gesture.Back, Gesture.Forward, Gesture.Refresh) as IPlatformNavigationService;

            ItemInvoked += PrismNavigationView_ItemInvokedAsync;

            Loaded += PrismNavigationView_Loaded;
        }

        public IPlatformNavigationService NavigationService { get; }

        public string SettingsUri { get; set; } = "/Settings";

        private Frame ContentFrame { get; }

        private async void ContentFrame_NavigatedAsync(object sender, NavigationEventArgs e)
        {
            if (TryFindItem(e.SourcePageType, e.Parameter, out var item))
            {
                await SetSelectedItemAsync(item);
            }
        }

        private NavigationViewItem FindItem(string content) => MenuItems.OfType<NavigationViewItem>().SingleOrDefault(i => i.Content.Equals(content));

        public async Task<IPlatformNavigationService> InitializeAsync()
        {
            var item = MenuItems.OfType<NavigationViewItem>().SingleOrDefault(x => (bool)x.GetValue(PrismNavigationViewProperties.IsStartPageProperty));

            if (item != null)
            {
                await SetSelectedItemAsync(item);
            }

            return NavigationService;
        }

        private bool IsItemRegistered(Type type) => PageRegistry.TryGetRegistration(type, out var info);

        private bool IsItemSettings(Type type, object parameter) => NavigationQueue.TryParse(SettingsUri, null, out var settings) && type == settings.Last().View && (string)parameter == settings.Last().QueryString;

        private void NavigationService_CanGoBackChanged(object sender, EventArgs e) => IsBackEnabled = NavigationService.CanGoBack();

        private async void PrismNavigationView_ItemInvokedAsync(NavigationView sender, NavigationViewItemInvokedEventArgs args) => await SetSelectedItemAsync(args.IsSettingsInvoked ? SettingsItem : FindItem(args.InvokedItem.ToString()));

        private void PrismNavigationView_Loaded(object sender, RoutedEventArgs e) => NavigationService.CanGoBackChanged += NavigationService_CanGoBackChanged;

        private async Task SetSelectedItemAsync(object selectedItem)
        {
            if (selectedItem == null)
            {
                SelectedItem = null;
            }
            else if (selectedItem == SettingsItem)
            {
                if (SettingsUri != null)
                {
                    await NavigationService.NavigateAsync(SettingsUri);

                    SelectedItem = selectedItem;
                }

                SettingsInvoked?.Invoke(this, EventArgs.Empty);
            }
            else if (selectedItem is NavigationViewItem item)
            {
                if (item.GetValue(PrismNavigationViewProperties.NavigationUriProperty) is string path)
                {
                    if ((await NavigationService.NavigateAsync(path)).Success)
                    {
                        SelectedItem = selectedItem;
                    }
                    else
                    {
                        throw new Exception($"{selectedItem}.{nameof(PrismNavigationViewProperties.NavigationUriProperty)} navigation failed.");
                    }
                }
                else
                {
                    throw new Exception($"{selectedItem}.{nameof(PrismNavigationViewProperties.NavigationUriProperty)} is not valid URI.");
                }
            }
        }

        private bool TryFindItem(Type type, object parameter, out object item)
        {
            if (!IsItemRegistered(type))
            {
                item = null;
                return false;
            }

            if (IsItemSettings(type, parameter))
            {
                item = SettingsItem;
                return true;
            }

            foreach (var menuItem in MenuItems.OfType<NavigationViewItem>().Select(i => new { Item = i, Path = i.GetValue(PrismNavigationViewProperties.NavigationUriProperty) as string }).Where(x => !string.IsNullOrEmpty(x.Path)))
            {
                if (NavigationQueue.TryParse(menuItem.Path, null, out var menuQueue) && Equals(menuQueue.Last().View, type))
                {
                    item = menuItem;
                    return true;
                }
            }

            item = null;
            return false;
        }
    }

    public partial class PrismNavigationViewProperties : DependencyObject
    {
        public static string GetNavigationUri(DependencyObject obj) => (string)obj.GetValue(NavigationUriProperty);
        public static void SetNavigationUri(DependencyObject obj, string value) => obj.SetValue(NavigationUriProperty, value);
        public static readonly DependencyProperty NavigationUriProperty = DependencyProperty.RegisterAttached("NavigationUri", typeof(string), typeof(NavigationView), new PropertyMetadata(null));

        public static bool GetIsStartPage(NavigationViewItem obj) => (bool)obj.GetValue(IsStartPageProperty);
        public static void SetIsStartPage(NavigationViewItem obj, bool value) => obj.SetValue(IsStartPageProperty, value);
        public static readonly DependencyProperty IsStartPageProperty = DependencyProperty.RegisterAttached("IsStartPage", typeof(bool), typeof(PrismNavigationViewProperties), new PropertyMetadata(false));
    }
}


来源:https://stackoverflow.com/questions/52926892/alternative-way-to-create-shell-in-prism-windows-7-1-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!