c# - 如何从其他页面初始化 ShellView(Windows 模板工作室)
问题描述
Windows 模板工作室:参考链接
我用Navigation Pane Type 和Prism Pattern创建了一个项目,我有 Settings 和一些页面
这是 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,所以我在Views文件夹下创建了一个SignInPage ,并在ViewModels文件夹下创建了SignInPageViewModel类。
我试图将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 委托命令绑定了命令,但它无法找到我的 viewmodel(ViewModelLocator.AutoWireViewModel="True"),所以我在我的应用程序.xaml.cs:
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.Register<SignInPage, ViewModels.SignInPageViewModel>();
}
问题 1:为什么它无法找到我的视图模型,即使它与自动创建的页面具有相同的命名空间?
现在按钮命令是导航到ShellPage,所以每当我单击按钮时,它将导航到ShellPage但 Frame 未正确初始化,因此当我尝试导航到任何页面时出现空引用错误。
问题 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
。
更新
如何在导航时初始化 ShellPage?
坦率地说,这种行为不适合当前的架构。因为默认情况下,应用程序只有一个rootFrame,但是由于你去掉了CreateShell方法的override,势必会引入第二个frame,这会导致未知错误。
session state
如果你坚持,我这里提供了一个方法,但是当软件关闭时它不会正确保存。
应用程序.xaml.cs
public static App Instance;
public App()
{
InitializeComponent();
Instance = this;
}
登录页面.xaml.cs
SignInButton_Click
请在 xaml 中收听事件
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));
}
}
此致。
推荐阅读
- excel - 从一个工作表复制并粘贴到另一个工作表
- javascript - 如何阻止所有欧洲 IP 地址?
- cross-domain - 如何在fabric js的SetBackgroundImage中设置跨域
- python - 如何修复“UnicodeEncodeError:'charmap'编解码器无法编码”?
- c - C - 大端结构与小端结构相互转换
- hyperledger-fabric - Hyperledger Fabric 事件存储在哪里?
- firebase - 将值从一个节点检索到另一个节点
- java - 尝试填充新数组后二元运算符“+”的操作数类型错误
- python - 只用 pandas 获取每组的第一行和最后一行
- c# - OpenXML-InnerText 始终是整数而不是字符串