Windows Template Studio: reference link
I created a project with Navigation Pane Type and Prism Pattern , I have Settings, and some pages
Here is the 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;
}
}
I want to show a SignInPage before showing the ShellPage , So I created a SignInPage under the Views folder and created SignInPageViewModel class under ViewModels folder.
I tried to changed OnLaunchApplicationAsync to:
protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
await LaunchApplicationAsync("SignIn", null);
}
and removed the:
protected override UIElement CreateShell(Frame rootFrame)
{
var shell = Container.Resolve<ShellPage>();
shell.SetRootFrame(rootFrame);
return shell;
}
Now my app startup page is my SignInPage, I have LogInButton on that page , and Bound the command from my viewmodel delegatecommand, but it was not able to locate my viewmodel(ViewModelLocator.AutoWireViewModel="True"), so I added this on my App.xaml.cs:
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.Register<SignInPage, ViewModels.SignInPageViewModel>();
}
QUESTION 1: Why it's not able to locate my viewmodel even it has the same namespace with the auto created pages?
Now the button command is to navigate to ShellPage , so whenever I click the button , it will navigate to ShellPage but the Frame is not initialize properly so I am getting a null reference error when I tried to navigate to any page.
Question 2: How can I initialize the ShellPage on navigated?
The problem may be in your naming.
Change SignInPageViewModel
to 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);
});
}
Please note this function, which is used to register the ViewModel of the current page. According to the corresponding naming convention, if the name of Page is {name}Page.xaml
, then ViewModel is {name}ViewModel.cs
.
Update
How can I initialize the ShellPage on navigated?
To be frank, such behavior does not fit the current architecture. Because by default, the application has only one rootFrame, but since you remove the override of the CreateShell method, it is bound to introduce a second frame, which will cause an unknown error.
If you insist, I provide a method here, but it will not save the session state
correctly when the software is closed.
App.xaml.cs
public static App Instance;
public App()
{
InitializeComponent();
Instance = this;
}
SignInPage.xaml.cs
Please listen for the SignInButton_Click
event in 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));
}
}
Best regards.