如何从其他页面初始化 ShellView (Windows Template Studio)

How can I initialize ShellView from other Page (Windows Template Studio)

Windows 模板工作室:reference link

我使用 导航窗格 类型和 Prism 模式创建了一个项目,我有设置和一些页面

这里是 App.xaml.cs:

[Windows.UI.Xaml.Data.Bindable]
public sealed partial class App : PrismUnityApplication
{
    public App()
    {
        InitializeComponent();
    }

    protected override void ConfigureContainer()
    {
        // register a singleton using Container.RegisterType<IInterface, Type>(new ContainerControlledLifetimeManager());
        base.ConfigureContainer();
        Container.RegisterInstance<IResourceLoader>(new ResourceLoaderAdapter(new ResourceLoader()));
        Container.RegisterType<ISampleDataService, SampleDataService>();
    }

    protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
    {
        await LaunchApplicationAsync(PageTokens.MainPage, null);
    }

    private async Task LaunchApplicationAsync(string page, object launchParam)
    {
        await ThemeSelectorService.SetRequestedThemeAsync();
        NavigationService.Navigate(page, launchParam);
        Window.Current.Activate();
    }

    protected override async Task OnActivateApplicationAsync(IActivatedEventArgs args)
    {
        await Task.CompletedTask;
    }

    protected override async Task OnInitializeAsync(IActivatedEventArgs args)
    {
        await base.OnInitializeAsync(args);
        await ThemeSelectorService.InitializeAsync().ConfigureAwait(false);

        //We are remapping the default ViewNamePage and ViewNamePageViewModel naming to ViewNamePage and ViewNameViewModel to
        //gain better code reuse with other frameworks and pages within Windows Template Studio
        ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
        {
            var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "App1.ViewModels.{0}ViewModel, App1", viewType.Name.Substring(0, viewType.Name.Length - 4));
            return Type.GetType(viewModelTypeName);
        });
    }

    protected override IDeviceGestureService OnCreateDeviceGestureService()
    {
        var service = base.OnCreateDeviceGestureService();
        service.UseTitleBarBackButton = false;
        return service;
    }

    public void SetNavigationFrame(Frame frame)
    {
        var sessionStateService = Container.Resolve<ISessionStateService>();
        CreateNavigationService(new FrameFacadeAdapter(frame), sessionStateService);
    }

    protected override UIElement CreateShell(Frame rootFrame)
    {
        var shell = Container.Resolve<ShellPage>();
        shell.SetRootFrame(rootFrame);
        return shell;
    }
}

我想在显示 ShellPage 之前显示一个 SignInPage ,所以我创建了一个 SignInPageViews 文件夹下,并在 ViewModels 文件夹下创建 SignInPageViewModel class。

我尝试将 OnLaunchApplicationAsync 更改为:

protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
    {
        await LaunchApplicationAsync("SignIn", null);
    }

并删除了:

protected override UIElement CreateShell(Frame rootFrame)
    {
        var shell = Container.Resolve<ShellPage>();
        shell.SetRootFrame(rootFrame);
        return shell;
    }

现在我的应用程序启动页面是我的 SignInPage,我在该页面上有 LogInButton,并绑定了来自我的 viewmodel delegatecommand 的命令,但它无法找到我的视图模型(ViewModelLocator.AutoWireViewModel="True"),所以我在 App.xaml.cs:

上添加了这个
protected override void ConfigureViewModelLocator()
    {
        base.ConfigureViewModelLocator();

        ViewModelLocationProvider.Register<SignInPage, ViewModels.SignInPageViewModel>();
    }

问题 1: 为什么它无法找到我的视图模型,即使它与自动创建的页面具有相同的命名空间?

现在按钮命令是导航到 ShellPage ,所以每当我单击按钮时,它都会导航到 ShellPage 但框架未正确初始化,因此当我尝试导航到任何页面时出现空引用错误。

问题 2:如何在导航时初始化 ShellPage?

问题可能出在你的命名上。

SignInPageViewModel 更改为 SignInViewModel

protected override async Task OnInitializeAsync(IActivatedEventArgs args)
{
    await base.OnInitializeAsync(args);

    //We are remapping the default ViewNamePage and ViewNamePageViewModel naming to ViewNamePage and ViewNameViewModel to
    //gain better code reuse with other frameworks and pages within Windows Template Studio
    ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
    {
        var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "App1.ViewModels.{0}ViewModel, App1", viewType.Name.Substring(0, viewType.Name.Length - 4));
        return Type.GetType(viewModelTypeName);
    });
}

请注意这个函数,用于注册当前页面的ViewModel。根据相应的命名约定,如果Page的名字是{name}Page.xaml,那么ViewModel就是{name}ViewModel.cs.


更新

How can I initialize the ShellPage on navigated?

坦率地说,这种行为不适合当前的架构。因为默认情况下,应用程序只有一个 rootFrame,但是由于您删除了 CreateShell 方法的重写,势必会引入第二个 frame,这将导致未知错误。

如果你非要坚持的话,我这里提供了一个方法,但是在软件关闭的时候不能正确保存session state

App.xaml.cs

public static App Instance;
public App()
{
    InitializeComponent();
    Instance = this;
}

SignInPage.xaml.cs

请收听 xaml

中的 SignInButton_Click 事件
private void SignInButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    var rootFrame = Window.Current.Content as Frame;
    var frame = new Frame();
    App.Instance.SetNavigationFrame(frame);
    rootFrame.Navigate(typeof(ShellPage), frame);
}

ShellPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if(e.Parameter is Frame frame)
    {
        SetRootFrame(frame);
        frame.Navigate(typeof(MainPage));
    }
}

此致。