如何从其他页面初始化 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 ,所以我创建了一个 SignInPage 在 Views 文件夹下,并在 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));
}
}
此致。
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 ,所以我创建了一个 SignInPage 在 Views 文件夹下,并在 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));
}
}
此致。