撰写本文时,MyGet Package中即将推出的Prism.Windows 7.1.0缺少重写方法 CreateShell() 我真的很想知道它是否将被转移到另一种方法中,或者将在最终版本中消失。
如果是这样,假设代码来自此tutorial并使用DryIoC容器,则实现shell视图的替代解决方案是什么。
答案 0 :(得分:0)
您可以使用CreateShell()
内的NavigationService
来代替使用NavigationView
替代。此答案中提供的代码是从三个Template10 Samples中的一个改编而来的,在撰写本文时,这三个Prism Samples尚未迁移到Sample Project (16299):Prism.Unity.Windows。应该注意的是,此答案使用了Prism.DryIoc.Windows,但是我认为可以轻松地将其交换为this或其他任何受支持的框架,而不会引起问题。
<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>
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;
}
}
}
<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="" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItemSeparator />
<NavigationViewItem controls:PrismNavigationViewProperties.NavigationUri="/Students" Content="Students">
<NavigationViewItem.Icon>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem controls:PrismNavigationViewProperties.NavigationUri="/Lecturers" Content="Lecturers">
<NavigationViewItem.Icon>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" />
</NavigationViewItem.Icon>
</NavigationViewItem>
</NavigationView.MenuItems>
</controls:PrismNavigationView>
</Page>
using Windows.UI.Xaml.Controls;
namespace StudentRecords.Uwp
{
public sealed partial class AppShell : Page
{
public AppShell() => InitializeComponent();
}
}
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));
}
}