Search code examples
xamarin.formsmvvmdata-bindingtabbedpageitemsource

How can i add ContentPages to a Tabbedpage programatically in ViewModel in Xamarin Forms


So, I am trying to build a Xamarin Forms Application where I have a tabbedPage which has n-Amount of ContentPages included.

My TabbedPage looks like this below:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
            xmlns:viewmodels="clr-namespace:TournamentManager_4.MVVM.ViewModels" 
            xmlns:models="clr-namespace:TournamentManager_4.MVVM.Models"
            x:Class="TournamentManager_4.MVVM.Views.RunTournamentPage"
            xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
            android:TabbedPage.ToolbarPlacement="Bottom"
            BarBackgroundColor="#2196F3"
            BarTextColor="White"
            android:TabbedPage.BarItemColor="#66FFFFFF"
            android:TabbedPage.BarSelectedItemColor="White"
            Title="{Binding Name}"
            ItemsSource="{Binding ObsColTabPages}">
    
    <TabbedPage.BindingContext>
        <viewmodels:RunTournamentViewModel/>
    </TabbedPage.BindingContext>

    <TabbedPage.ItemTemplate>
        <DataTemplate x:DataType="models:Battle">
            <ContentPage BindingContext="{Binding CurrentPage}" Title="{Binding Round}">
            </ContentPage>
        </DataTemplate>

    </TabbedPage.ItemTemplate>
</TabbedPage>

I have a ViewModel which is called RunTournamentViewModel, where I have an Observable Collection of the Model: Battle:

  public class RunTournamentViewModel : ViewModelBase
     {
        public ObservableCollection<Battle> ObsColTabPages { get; set; }
        public RunTournamentViewModel()
        {
        
            ObsColTabPages = new ObservableCollection<Battle>();
        }

          private void AddTabPage()
        {
           
            for (int i = 0; i < Rounds; i++)
            {
                ObsColTabPages.Insert(0, new Battle()
                {
                    Round = GetRoundName(i),
                    CurrentPage = new BattlePage()
        
                }) ;
               
            }
        }
    }
  public class Battle
    {
        public string Round { get; set; }
        public ContentPage CurrentPage { get; set; }
    }

Then I have a ContentPage, named "BattlePage" where I want to create some instances of it and put those into my ObservableCollection to show its content.

The Itemssource of my TabbedPage just works fine. In my Application,I get the amount of Tabs I want. But it does not show the Content of the "BattlePage".

I think the Problem is that I got the Binding wrong. I just tried some stuff like the following:

BindingContext="{Binding CurrentPage}

I expected that it would display the Battlepage, but it does not.

Is there a solution or a workaround to this Problem? Thanks for your help!


Solution

  • You can add the child pages to your tabbedpage in Viewmodel like below:

    public class tabbedpageviewmodel : ViewModelBase
    {
        public ObservableCollection<Page> tabs { get; set; }
        private Page _selectedtab;
        public Page selectedtab
        {
            get { return _selectedtab; }
            set
            {
    
                RaisePropertyChanged("selectedtab");
            }
        }   
        public tabbedpageviewmodel()
        {
            tabs = new ObservableCollection<Page>();
            tabs.Add(new Page1() { BindingContext = new page1viewmodel() });
            tabs.Add(new Page2() { BindingContext = new page2viewmodel() });
            selectedtab = tabs[0];
        }
    }
    

    For more details, you can refer to this one: https://stackoverflow.com/a/61004534/9644964.