Альтернативный способ создания оболочки в Prism.Windows 7.1.0? - PullRequest
0 голосов
/ 22 октября 2018

На момент написания этой статьи в готовящейся Prism.Windows 7.1.0 из пакета MyGet отсутствует метод переопределения CreateShell () , и мне действительно интересно, будет ли он перемещен в другой метод или он исчезнетв окончательном выпуске.

Если да, то каково альтернативное решение для реализации представления оболочки, если предположить, что код взят из этого учебника , а вместо него используется контейнер DryIoC.

1 Ответ

0 голосов
/ 09 ноября 2018

Вместо использования CreateShell() можно создать NavigationService внутри NavigationView.Код, приведенный в этом ответе, адаптирован из одного из трех образцов10 образцов , который на момент написания не был перенесен в образцов призмы : образцаПроект (16299) .Следует отметить, что в этом ответе используется Prism.Unity.Windows , однако я могу предположить, что его можно легко заменить на Prism.DryIoc.Windows или любую другую поддерживаемую платформу,без проблем.

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