miechooy
miechooy

Reputation: 3422

Xamarin.Forms: Display additional tab on specific Platform

Good morning

I have a TabbedPage in my application. Due to restictions I would like to display one more tab on Android than on iOS.

My current TabbedPage look like:

<TabbedPage>

...

<ContentPage x:Name="Page1"/>
<ContentPage x:Name="Page2"/>
<ContentPage x:Name="Page3"/>
<ContentPage x:Name="Page4"/>
</TabbedPage>

I have decided to render Page3 only for Android. I changed my code into:

<TabbedPage>

...

<ContentPage x:Name="Page1"/>
<ContentPage x:Name="Page2"/>

<OnPlatform x:TypeArguments="Page">
    <On Platform="Android">
        <On.Value>
            <ContentPage x:Name="Page3"/>
        </On.Value>
    </On>
</OnPlatform>

<ContentPage x:Name="Page4"/>
</TabbedPage>

This leads to runtime exception when entering into this TabbedPage:

An error occurred: 'Value cannot be null. Parameter name: item'. Callstack: ' at Xamarin.Forms.ObservableWrapper`2[TTrack,TRestrict].Add (TRestrict item) [0x00008] in D:\a\1\s\Xamarin.Forms.Core\ObservableWrapper.cs:27

I tried to remove x:Name but did not work. Any ideas?

PS. As a workaround I am always able to:

Constructor()
{
   if(Runtime.IsIOS)
   {
       this.Children.Remove(this.Page3)  
   }
}

However would be better to not render it at all and have it at XAML level.

Upvotes: 0

Views: 110

Answers (2)

Adrain
Adrain

Reputation: 1934

According to this,xaml is an alternative to programming code for instantiating and initializing objects, and organizing those objects in parent-child hierarchies.If you add one additional tab on android it will cause a NullReferenceException on ios.So you may want to do it in codebehind with Device.RuntimePlatform. Here is my test you can refer to:

switch (Device.RuntimePlatform)
        {
            case Device.Android:
                Children.Add(page1);
                Children.Add(page2);
                break;
            case Device.iOS:
                Children.Add(page1);
               
                break;
            case Device.UWP:
                Children.Add(page1);
                break;
        }

Upvotes: 0

ToolmakerSteve
ToolmakerSteve

Reputation: 21253

Unless someone comes up with a way to do this in XAML, this is the best you can do (building on Jason's comment):

xaml:

<ContentPage x:Name="Page1"/>
<ContentPage x:Name="Page2"/>
<!-- no Page3 in XAML -->
<ContentPage x:Name="Page4"/>

c#:

private ContentPage page3;

Constructor()
{
    InitializeComponent();

    if (Runtime.IsAndroid)
    {
        page3 = new ContentPage();
        // After pages 1 and 2.
        Children.Insert(2, page3);
    }
}

    // Elsewhere in code-behind.
        if (page3 != null)
        {
            ...refer to page3...
        }

This has the advantage of not constructing the page at all on iOS.
It also makes it easy to test whether page3 is there (page3 != null).

In practice, the other pages will typically be their own classes. Given partial class Page3 : ContentPage elsewhere:

private Page3 page3;

    ...
    page3 = new Page3();

Upvotes: 1

Related Questions