【问题标题】:Alternative way to create shell in Prism.Windows 7.1.0?在 Prism.Windows 7.1.0 中创建外壳的替代方法?
【发布时间】:2018-10-22 10:12:13
【问题描述】:

在撰写本文时,MyGet Package 即将推出的 Prism.Windows 7.1.0 缺少覆盖方法 CreateShell() 我真的很想知道它是否会被转移到另一种方法中,或者它会在最终版本中消失。

如果是这样,假设代码来自此tutorial 并改用 DryIoC 容器,那么实现 shell 视图的替代解决方案是什么。

【问题讨论】:

    标签: uwp prism dryioc


    【解决方案1】:

    您可以在NavigationView 内创建NavigationService,而不是使用CreateShell() 覆盖。此答案中提供的代码改编自三个Template10 Samples 之一,在撰写本文时,尚未迁移到Prism SamplesSample Project (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));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      相关资源
      最近更新 更多