How to 'include' NavigationPage in XAML

AleksanderKobylak.6525AleksanderKobylak.6525 USMember
edited September 2015 in Xamarin.Forms

Hi,

I'm trying to make as much work as possible in XAML. Is it possible to 'include'/embed XAML with NavigationPage into another XAML?

Example - MenuPage:

        <?xml version="1.0" encoding="UTF-8"?>
        <MasterDetailPage 
            xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
            x:Class="MyApp.MenuPage"
            xmlns:local="clr-namespace:MyApp;assembly=MyApp"
            Style="{StaticResource PageStyle}"
            Title="MyApp">

            <MasterDetailPage.Master Title="Menu">
                <local:Menu/>
            </MasterDetailPage.Master>

            <MasterDetailPage.Detail>
                <local:DashboardPage/>
            </MasterDetailPage.Detail>
        </MasterDetailPage>

and my DashboardPage looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<NavigationPage
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="MyApp.DashboardPage" 
    xmlns:local="clr-namespace:MyApp;assembly=MyApp"
    Style="{StaticResource NavigationPageStyle}">

    <x:Arguments>
        <local:UTTabbedPage Title="Dashboard" Style="{StaticResource TabbedPageStyle}">
            <local:UTTabbedPage.Children>
            <local:ObjectsPage />               
                <local:HostsPage />
                <local:ServicesPage />
            </local:UTTabbedPage.Children>
        </local:UTTabbedPage>
    </x:Arguments>
</NavigationPage>

After login page I'm loading MenuPage like this:
Application.Current.MainPage = new MenuPage();

When I copy my DashboardPage directly into MenuPage everything works as expected. But when I try to embed DashboardPage into MenuPage I have error: "NavigationPage must have a root Page before being used. Either call PushAsync with a valid Page, or pass a Page to the constructor before usage."

Any idea?

Tagged:

Answers

  • adamkempadamkemp USInsider, Developer Group Leader mod

    What does the code for DashboardPage look like?

  • Good question. Code-behind for DashboardPage:

    using System;
    using System.Collections.Generic;
    
    using Xamarin.Forms;
    
    namespace MyApp
    {
        public partial class DashboardPage : NavigationPage
        {
            static public NavigationPage DashboardNavPage { get; set; }
    
    
            public DashboardPage()
            {
                InitializeComponent();
    
                DashboardNavPage = this;
            }
        }
    }
    
  • adamkempadamkemp USInsider, Developer Group Leader mod

    You probably need a constructor that takes a Page argument and passes that up to the base class. I believe that is what the x:Arguments XAML code will try to call. Try this:

        public DashboardPage(Page page) : base(page)
        {
            InitializeComponent();
    
            DashboardNavPage = this;
        }
    
  • Unfortunately - not working.
    Now there is error regarding missing default constructor:
    Default constructor not found for type MyApp.DashboardPage

    It's happening (at least exception is thrown) in generated MenuPage code:

     public partial class MenuPage : MasterDetailPage {
    
            [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
            private void InitializeComponent() {
                this.LoadFromXaml(typeof(MenuPage));
            }
        }
    
  • adamkempadamkemp USInsider, Developer Group Leader mod

    Seems like your x:Arguments isn't being used. Make sure you're using that right. I've never used it myself (only learned about it recently) so I can't say if it's right.

  • ylemsoulylemsoul RUMember ✭✭✭
    edited September 2015

    If you write
    <MasterDetailPage.Detail> <local:DashboardPage /> </MasterDetailPage.Detail>
    then DashboardPage will be created with parameterless constructor by the parser. Next it will call InitializeComponent(). But as Adam said x:Arguments inside DashboardPage's XAML is not used because instance already have been created.

    I would restructure to this:

    1) DashboardPage with constructor that accept a Page as Adam pointed out
    2) MasterDetailPage.Detail:
    <MasterDetailPage.Detail> <local:DashboardPage> <x:Arguments> <local:UTTabbedPage /> </x:Arguments> </local:DashboardPage> </MasterDetailPage.Detail>
    3) UTTabbedPage:
    <TabbedPage .. > <TabbedPage.Children> <local:ObjectsPage /> <local:HostsPage /> <local:ServicesPage /> <TabbedPage.Children> </TabbedPage>

  • Better, because it's not crashing anymore :)

    But now there is problem: TabbedPage is not showing.
    I've changed approach to navigation in this specific app, but would be good to find some solution of embedding NavigationPage in xaml.

  • ylemsoulylemsoul RUMember ✭✭✭

    Can you show what have been changed for the UITabbedPage?

  • Sorry - my fault!
    When I wanted to copy code from master-detail I've noticed that my tabbed page has old name.
    Your solution is working - many thanks for help.

    So just to sum up:

    MasterDetailPage.xaml:

    <MasterDetailPage ...>
    
        <MasterDetailPage.Master Title="Menu">
            <local:Menu/>
        </MasterDetailPage.Master>
    
    
        <MasterDetailPage.Detail>
    
            <local:DashboardPage>
                <x:Arguments>
    
                    <local:Tabs/>
    
                </x:Arguments>
    
            </local:DashboardPage>
    
        </MasterDetailPage.Detail>
    
    </MasterDetailPage>
    

    DashboardPage.xaml:

    <NavigationPage...>
    
        <x:Arguments />
    
    </NavigationPage>
    

    DashboardPage.xaml.cs:

    public partial class DashboardPage : NavigationPage
        {
            static public NavigationPage DashboardNavPage { get; set; }
    
            public DashboardPage(Page page) : base(page)
            {
                InitializeComponent();
    
                DashboardNavPage = this;
            }
        }
    

    Tabs.xaml:

         <local:UTTabbedPage   ... >
                    <local:UTTabbedPage.Children>
                    <local:ObjectsPage />           
                    <local:HostsPage />
                            <local:ServicesPage />
                        </local:UTTabbedPage.Children>
        </local:UTTabbedPage>
    
  • AbhishekPathakAbhishekPathak USMember
    edited January 2016

    Hi, AleksanderKobylak.6525 can you share your whole code please because i am facing same issue.....

  • YimingHsuYimingHsu USMember ✭✭

    @AleksanderKobylak.6525

    This is possible.

    I made a gist explaining the Navigationpage in Xaml

    https://gist.github.com/Easter1021/c2ed3e4f53c939bd3a2a64c400d682e9

Sign In or Register to comment.