Reusing Xamarin.Forms Pages: The Windows Phone case.
In the last entry we were talking about how to reuse the Xamarin.Forms Pages in a fully native Xamarin application for Android and iOS. The idea is to keep the use of Xamarin.Forms in the place where it fits: when we have simple views or views that follow the guidelines. Now we are going to see how to achieve that in Windows Phone 8.1.
To set up Xamarin.Forms in a Windows Phone 8.1 project, we have to add Xamarin.Forms.Forms.Init(e); being e of the type LaunchActivatedEventArgs. We have to call it in the App file. You can see more details of the setup process here
The approach will be similar of what we did on Android. We are going to have a Windows Phone Page which will be our MainPage, the responsible of showing our Xamarin.Forms Pages.
Just a reminder of the previous post, we had the following interface:
publicinterface INavigationService {
void OpenPage(int number);
}
Let’s start by implementing our Navigation interface:
publicclass WindowsPhoneNavigationService : INavigationService {
public Page CurrentPage { get; set; }
public WindowsPhoneNavigationService(Page startPage){
CurrentPage = startPage;
}
publicvoid OpenPage(int number) {
if (number == 2){
CurrentPage.Frame.Navigate(typeof(Page2), this);
return;
}
var page = number == 1 ? new Page1(this) as Xamarin.Forms.Page : new Page3(this) as Xamarin.Forms.Page;
var args = new Tuple<Xamarin.Forms.Page, WindowsPhoneNavigationService>(page, this);
CurrentPage.Frame.Navigate(typeof(MainPage), args);
}
}
We made the CurrentPage property public because after initialising the Windows Phone Page, we have to set the current page in our NavigationService in order to open new Pages (yes, it’s a bit dirty). Notice that we passed a tuple of Xamarin.Forms.Page * WindowsNavigationService to the MainPage.
publicsealedpartialclass MainPage
{
public MainPage() {
this.InitializeComponent();
}
protectedoverridevoid OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
Xamarin.Forms.Page page = null;
var isFirstTime = e.Parameter is string;
if (isFirstTime) {
var navService = new WindowsPhoneNavigationService(this);
page = new Page1(navService);
}
else {
var args = e.Parameter as Tuple<Xamarin.Forms.Page, WindowsPhoneNavigationService>;
page = args.Item1;
args.Item2.CurrentPage = this;
}
LoadApplication(new FakeApp(page));
}
This time, I created a FakeApp as an inner class to set up the Xamarin.Form.Page in our MainPage. So if it’s the first time, it initialises the WindowsNavService and then sets the first Page, and if it does not, it just uses the parameter passed in the NavigationService.
And finally, our native page:
publicsealedpartialclass Page2 : Page
{
WindowsPhoneNavigationService navService;
public Page2()
{
this.InitializeComponent();
}
protectedoverridevoid OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
navService = e.Parameter as WindowsPhoneNavigationService;
navService.CurrentPage = this;
}
void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
navService.OpenPage(3);
}
}
When programming on the Windows Platform, many people decide to handle the Navigation in the Views, I think that the responsibility of knowing where to go next belongs to the ViewModel. If you are doing cross platform development, you have no choice. If you don’t, it can be ok. After all, both are application services.