How to display content from one xaml inside another

CaseCase USMember ✭✭✭

I'm used to Android development, and am having some difficulty accomplishing what I would think is a simple task.

I have a MasterDetailPage (called ContainerView.xaml).
The Master is my navigation bar (called NavBarView.xaml).
The Details is supposed to be a page with a fixed title bar, and a "view" I can swap per user choices.
The Details page is called MainView.xaml.
The Title I'd like to display at the top and is called TitleBarView.xaml.
Then I have a number of content pages such as Page1View.xaml.

in my ContainerView.xaml:

<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"             
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"       
                  x:Class="MyApp.ContainerView"
                  IsGestureEnabled="True"
                  MasterBehavior="Popover"
                  Title="MasterDetail Page">
  <MasterDetailPage.Master>
  </MasterDetailPage.Master>
  <MasterDetailPage.Detail>
  </MasterDetailPage.Detail>  
</MasterDetailPage>

in my NavbarView.xaml - this is the Master

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="MyApp.NavBarView"
             Title="Nav Bar">  
  <ContentPage.Content>  
    <StackLayout Orientation="Vertical">
      <Label Text="{Binding Item1}"/>
      <Button Text="Options" Command="{Binding Option1Command}"/>
    </StackLayout >
  </ContentPage.Content>  
</ContentPage>

in my MainView.xaml - this is the details

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.MainView"
             Title="Main View">
  <ContentPage.Content>
  // what to put here to show the TitleBarView.xaml?
  // what to put here to show my content xaml pages?
  </ContentPage.Content>
</ContentPage>

in my TitleBarView.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.TitleBarView">
  <ContentView.Content>    
    <StackLayout Orientation="Horizontal">
      <Label Text="{Binding Item1}"/>
      <Button Text="Options" Command="{Binding OptionsCommand}"/>
    </StackLayout>    
  </ContentView.Content>
</ContentView>

and a generic content view, of course there will be many others I want to switch between

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.Page1View">
  <ContentView.Content>
    <StackLayout Orientation="Vertical">
      <Label Text="{Binding Info}"/>
      <Button Text="Log In" Command="{Binding GoToPage2Command}"/>
    </StackLayout >
  </ContentView.Content>
</ContentView>

I am using the MVVM model and have this code, but can't seem to get just the basics working.
The Master page displays fine.
If the Details page is just a simple page, it works, but I can't figure out how to insert the TitleBar and swap out the "Content".

ContainerView containerPage = new ContainerView();
ContainerViewModel containerVM = new ContainerViewModel();
containerPage.BindingContext = containerVM;

NavBarView navigationBar = new NavBarView();
navigationBar.Title = "Navigation Bar"; // required, otherwise I get an exception.
NavBarViewModel navigationBarVM = new NavBarViewModel();
navigationBar.BindingContext = navigationBarVM;

MainView mainView = new MainView();
mainView.Title = "MainView";
MainViewModel mainViewVM = new MainViewModel();
mainView.BindingContext = mainViewVM;

TitleBarView titleBar = new TitleBarView();
TitleBarViewModel titleBarVM = new TitleBarViewModel();
titleBar.BindingContext = titleBarVM;

Page1View page1 = new Page1View();
Page1ViewModel page1VM = new Page1ViewModel();
page1.BindingContext = page1VM;

mainView.Content = new StackLayout()
{
    Orientation = StackOrientation.Vertical,
    Children = 
    {
        new Label { Text = "I'm Content!" },
        new Label { Text = "I'm Content!" },
        //titleBar.Content,
        //loginView.Content
    }
};

containerPage.MasterBehavior = MasterBehavior.Popover;
containerPage.Master = navigationBar;
containerPage.Detail = new NavigationPage(mainView);

I'm sure I'm missing a fundamental concept. Any help would be appreciated

Best Answer

Answers

  • requenaxiirequenaxii USMember ✭✭

    Thanks @AlexDunn, it's a very easy way (I need to put more attention on my XAML skills).

    I have a question from that, I use the native navigation bar on my project and change between ContentViews through a CustomTabLayout in order to use the same design on Android and iOS but, I don't know how to change the Title when I switch between Views.

    I hope you can give me an approach. Thanks.

  • Rohit_ArnavRohit_Arnav USMember ✭✭

    @requenaxii
    public static readonly BindableProperty HeaderTextProperty = BindableProperty.Create("HeaderText", typeof(string), typeof(HomePage), "Home Page");
    public string HeaderText
    {
    get { return (string)GetValue(HeaderTextProperty); }
    }

    use this in your all content page and change the "Home Page" with what u want your title..

  • JassimRahmaJassimRahma USMember ✭✭✭

    I tried that but did not not @AlexDunn

    My Main page is:

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="Zeera.ZeeraPage"
        ControlTemplate="{StaticResource MainPageTemplate}"
        xmlns:views="Zeera.MyPage">
        <ContentPage.Content>
            <StackLayout HorizontalOptions="Center" VerticalOptions="StartAndExpand">
                <Label Text="tems Items Items Items Items Items Items Items  " />
            </StackLayout>
            <views:MyPage />
        </ContentPage.Content>
    </ContentPage>
    

    and the page I want to put inside the main page is:

    <?xml version="1.0" encoding="UTF-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="Zeera.MyPage">
        <ContentPage.Content>
        </ContentPage.Content>
    </ContentPage>
    

    Kindly help...

    Thanks,
    Jassim

  • CaseCase USMember ✭✭✭

    @JassimRahma You can't put a ContentPage inside of a ContentPage. Make what you want to insert a ContentView and it should work.

    What I do in my apps is have a single MainPage that is a content page, and make all my "pages" actually be ContentViews. Then just swap out the content as I navigate.

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MyApp.Views.MainPage">
    
        <ContentPage.Content>
    
            <AbsoluteLayout HorizontalOptions="FillAndExpand" 
                            VerticalOptions="FillAndExpand"
                            BackgroundColor="LightGray">
    
                <ContentView x:Name="Container" 
                             HorizontalOptions="FillAndExpand" 
                             VerticalOptions="FillAndExpand" 
                             AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
                             AbsoluteLayout.LayoutFlags="All" />
    
                <ActivityIndicator IsVisible="{Binding IsBusy}" 
                                   IsRunning="{Binding IsBusy}" 
                                   IsEnabled="True" 
                                   Color="Black" 
                                   AbsoluteLayout.LayoutBounds="0.5, 0.5, 0.5, 0.5"
                                   AbsoluteLayout.LayoutFlags="All" />
    
            </AbsoluteLayout>
    
        </ContentPage.Content>
    
    </ContentPage>
    
    
    public NavigationController()
    {
        ContainerPage = new MainPage();
    }
    
    protected ViewModel currentViewModel = null;
    
    protected ContentPage _ContainerPage;
    public ContentPage ContainerPage
    {
        get { return _ContainerPage; }
        set
        {
            if (value != _ContainerPage)
            {
                _ContainerPage = value;
            }
        }
    }
    
    protected View _Content;
    public View Content
    {
        protected get { return _Content; }
        set
        {
            if (value != _Content)
            {
                _Content = value;
                ContainerPage.FindByName<ContentView>("Container").Content = value;
            }
        }
    }
    
    public void SetContent(Type vType)
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            ContentView content = (ContentView)Activator.CreateInstance(vType);
            currentViewModel = (ViewModel)content.BindingContext;
            Content = content;
        });
    }
    
  • JassimRahmaJassimRahma USMember ✭✭✭

    I removed the ContentPage but still having trouble..

    <?xml version="1.0" encoding="utf-8" ?>
    <StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Zeera.MyPage"
    Orientation="Horizontal"
    HorizontalOptions="FillAndExpand" Padding="10" BackgroundColor="White">
    <Button Text="Internal 1"  />
    <Button Text="Internal 2"  />
    </StackLayout>
    
    
    using System;
    using System.Collections.Generic;
    
    using Xamarin.Forms;
    
    namespace Zeera
    {
        public partial class MyPage: StackLayout
        {
            public MyPage()
            {
                InitializeComponent();
            }
        }
    }
    
  • RaedARaedA Member

    @Case @AlexDunn I tried this and it's worked fine with me.
    I need to know how can I change the content view by button inside the ContentPage ?

  • CaseCase USMember ✭✭✭

    @ReadA Here's what I do ...

    In your ContentPage, have a named ContentView. For example

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:viewModels="clr-namespace:MyApp.ViewModels;assembly=MyApp"
                 x:Class="MyApp.MainPage">
        <ContentPage.BindingContext>
            <viewModels:MainViewModel/>
        </ContentPage.BindingContext>
        <ContentPage.Content>
            <AbsoluteLayout HorizontalOptions="FillAndExpand" 
                            VerticalOptions="FillAndExpand"
                            BackgroundColor="LightGray">
                <ContentView x:Name="MainPageContainer" 
                             HorizontalOptions="FillAndExpand" 
                             VerticalOptions="FillAndExpand" 
                             AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
                             AbsoluteLayout.LayoutFlags="All" />
            </AbsoluteLayout>
        </ContentPage.Content>
    </ContentPage>
    

    Then you can create as many ContentViews as you want.

    <ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:viewModels="clr-namespace:MyApp.ViewModels;assembly=MyApp"
                 x:Class="MyApp.Content1View">
        <ContentView.BindingContext>
            <viewModels:Content1ViewModel/>
        </ContentView.BindingContext>
        <ContentView.Content>
            <StackLayout Orientation="Vertical">
                <Label Text="My Content 1"/>
            </StackLayout>
        </ContentView.Content>
    </ContentView>
    

    To "set" the current content when a button is clicked, just do something like

    _mainPage.FindByName<ContentView>("MainPageContainer").Content = (ContentView)Activator.CreateInstance(Content1View);
    
  • RaedARaedA Member

    @Case Thanks for your reply.
    It's not worked with me as well. I've used IsVisible to switch between different view by clicking on the button.

Sign In or Register to comment.