In the first post on Getting Started with BuildIt.Lifecycle I touched on the notion of an application region being a logical representation of a Window that’s part of an application. Most Windows Phone, iOS and Android applications will only have a single region but the very nature of Windows lends itself to multi-windowed applications. In this post we’ll extend the sample application to launch a new Window by creating a new region within the application. We’ll start with the declaration of the region:
public enum AdditionalStates
{
Base,
Landing
}
public class AdditionalRegion : StateAwareApplicationRegion
{
public AdditionalRegion()
{
StateManager.GroupWithViewModels<AdditionalStates>()
.StateWithViewModel<AdditionalStates, LandingViewModel>(AdditionalStates.Landing)
.OnComplete(DefaultCompletion.Complete)
.CloseRegion(this)
.EndState();
}
protected override async Task CompleteStartup()
{
await base.CompleteStartup();
await StateManager.GoToState(AdditionalStates.Landing, false);
}
}
You may notice this is slightly different from the PrimaryRegion I defined in my initial post as it inherits from the StateAwareApplicationRegion instead of just ApplicationRegion, and that there’s no StateManager property. The StateAwareApplicationRegion was added as a convenience class, which contains the StateManager property and implements the IHasStates interface. Note that both regions in my sample application now inherit from this class.
There is only a single state defined for the AdditionalRegion, which will correlate to the only page that will get loaded. When this region is started, the state manager transitions to the Landing state, which will display the LandingPage. In order for this to work, we need to create and correlate a LandingPage to the Landing state. I’ve added a page to the application based on the Blank Page template, called LandingPage. In App.xaml.cs I then needed to add the association between the new page and the Landing state:
LifecycleHelper.RegisterView<LandingPage>().ForState(AdditionalStates.Landing);
On the MainPage of the application I’ve added another Button which simply calls a new OpenAnotherWindow method on the MainViewModel.
private void AnotherWindowClick(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
ViewModel.OpenAnotherWindow();
}
The OpenAnotherWindow method simply calls OnComplete with a new enumeration value of AnotherWindow (this enumeration value is independent of the fact that I’ll be using it to open a new window, I could have called it “ShowMeTheMoney” so long as it correlates to the handler I’ll define in the PrimaryRegion).
public void OpenAnotherWindow()
{
OnComplete(MainCompletion.AnotherWindow);
}
As I just mentioned, I need to define what happens when OnComplete is called. To do this I need to update the state declarations in the PrimaryRegion. Here you can see the additional OnComplete which handles the AnotherWindow enumeration value, and calls LaunchRegion.
StateManager.GroupWithViewModels<AppStates>()
.StateWithViewModel<AppStates, MainViewModel>(AppStates.Home)
.OnCompleteWithData(MainCompletion.Settings,vm=>vm.HelloWithTime)
.ChangeState(AppStates.Settings)
.OnCompleteWithData< AppStates, MainViewModel,MainCompletion,string>(MainCompletion.About,null)
.ChangeState(AppStates.About)
.WhenChangedTo(async vm => await vm.LoadData())
.OnComplete(MainCompletion.AnotherWindow)
.LaunchRegion(this,TypeHelper.Ref<AdditionalRegion>())
.EndState()
Note: The TypeHelper is there to try to eliminate the need to specify all the Type arguments for the LaunchRegion method. I’ll look to refactor this more as we go to make it less obtuse to use.
That’s it, when you run the application, clicking the new Button will spawn of new windows (and actually will keep spawning new windows each time you click the button, even if the previous window is still open).