Tag: TabbedPage

When developing cross platform apps with Xamarin forms, you’ll notice that your apps will look and feel right at home on each OS. This because the nice people of Xamarin render each Xamarin forms control as a native control with the needed control properties all filled in.
You can still tweak some of these properties when they are leveraged through the Xamarin forms control abstraction or use custom renderers and effects to get down to the native control layer.

Most of the time this is all working great, but when you try to take UWP into account, you’ll notice not everything works straight out of the box.
Hence this blog post, showing you how you can hack the current TabbedPage implementation of Xamarin forms for UWP to enable pivot headers with images!

If you’ll use following XAML in Xamarin forms, you’ll get a nice Pivot control in UWP

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"

xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

xmlns:local="clr-namespace:TabbedPage"

x:Class="TabbedPage.MainPage">

<NavigationPage Title="Schedule 1"Icon="first.png">

<x:Arguments>

<local:SchedulePage/>

</x:Arguments>

</NavigationPage>

<NavigationPage Title="Schedule 2"Icon="second.png">

<x:Arguments>

<local:SchedulePage/>

</x:Arguments>

</NavigationPage>

</TabbedPage>

But when you run the app, you’ll notice that on UWP nothing is happening with the Icon property of the NavigationPage

While on iOS you’ll get something like this

So what gives? Well, the current Xamarin forms tabbed page implementation will not take into account this Icon property and ignore it during rendering.
Reading the guidelines from Microsoft, it’s recommended to actually do use icons for pivot headers if possible, read on it here https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/tabs-pivot.
The result should be something like this

Now let me show you a hack / workaround to get the same result on UWP. I stress hack, because of the current TabbedPage implementation in Xamarin forms there is no direct way to handle this.

To create a working solution, we need to change the HeaderTemplate that is specified inside that TabbedPageStyle. Normally we would just drop in a new Style with the same name inside our UWP App.Xaml file to override the one from Xamarin forms. But due to how Xamarin forms is initialised during startup this won’t work. So a small interception has to be made to get this going.

Add a new Styles.Xaml file in your UWP project and add following Style element to it

This will enable the use of the Icon property that we have set in our Xamarin forms xaml for each tab of the tabbedPage. Only thing left is swapping out the current HeaderTemplate and using ours.
So be sure to tell UWP we have this Style in our ResourceDictionary by adding it in the App.Xaml

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<Application

x:Class="TabbedPage.UWP.App"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="using:TabbedPage.UWP"

RequestedTheme="Light">

<Application.Resources>

<ResourceDictionary>

<ResourceDictionary.MergedDictionaries>

<ResourceDictionary Source="Styles.xaml"/>

</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

</Application.Resources>

</Application>

After that, open up the App.Xaml.cs file and look for the Xamarin.Forms.Forms.Init(e); line.
Below it add an extra line of code to do the actual Template swapping

Like I said this is a hack… but it works perfectly 🙂 instead of using the default Xamarin forms TabbedPageStyle inside the Pivot header template we’ll now be using our own TabbedPageStyle2.
Only one small detail remains, you’ll notice I added a converter inside the Style. This was needed because the Icon property on the NavigationPage of Xamarin forms maps to a FileImageSource but that is not processable straight away as a source value for the Image control inside UWP.

The converter will get the File property of the FileImageSource and return that as a valid source. With this in place you’ll get the correct image shown!