Search code examples
xamldata-bindingmauisyncfusion

.NET MAUI - Tabview Content use Binding Model for new page name


I currently have a Tab View which opens Content Views as separate Pages within the view. I have bound the tabs and images and also have a bound item for the page to call, I am struggling on the marked line to use my bound value:

My Main ContentPage is as follows :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="MauiApp1.StaticTabView"
            xmlns:local="clr-namespace:MauiApp1"
             xmlns:page="clr-namespace:MauiApp1.View"
            xmlns:tabView="clr-namespace:Syncfusion.Maui.TabView;assembly=Syncfusion.Maui.TabView"
            BackgroundColor="Black">
    <ContentPage.BindingContext>
        <local:TabItemsSourceViewModel />
    </ContentPage.BindingContext>
    <tabView:SfTabView ItemsSource="{Binding TabItems}" TabBarHeight="72" >
        <tabView:SfTabView.HeaderItemTemplate>
            <DataTemplate>
                <StackLayout>
                    <Image Source="{Binding ImageName}" HeightRequest="72" WidthRequest="72"/>
                </StackLayout>    
            </DataTemplate>
        </tabView:SfTabView.HeaderItemTemplate>
        <tabView:SfTabView.ContentItemTemplate>
            <DataTemplate>
                <page:test /> <!-- Here is my Issue I need to bind this value -->
            </DataTemplate>
        </tabView:SfTabView.ContentItemTemplate>    
    </tabView:SfTabView>    
</ContentPage>

For the Line I have a page called test which it calls, but I need this to be dynamic and bound:-

<page:test />

I was hoping or trying to put something like, which does not work I can not figure out how to get a bound value at this section. :-

<page: "{Binding PageName}" />

For the life of me I can not figure out how to do this :)

Any help would be appreciated, thank you in advance.


Solution

  • Given a string containing a page's name, make a DataTemplate containing an instance of that page.
    This can be done using an IValueConverter.

    Usage:

    <ContentPage ...
                 xmlns:local="clr-namespace:YourNameSpace"
                 x:Class=... >
        <ContentPage.Resources>
            <local:NameToPageTemplateConverter x:Key="nameToPageTemplateConverter" />
        </ContentPage.Resources>
        ...
        <tabView:SfTabView ...
            ContentItemTemplate="{Binding PageName, Converter={StaticResource nameToPageTemplateConverter}}"
            ... >
            <tabView:SfTabView.HeaderItemTemplate>
            ...
        </tabView:SfTabView>
    

    where PageName is a property, in current BindingContext, similar to ImageName.

    Declaration: a .cs file containing NameToPageTemplateConverter:

    namespace YourNameSpace   <-- must match namespace in `xmlns:local` declaration above.
    {
      public class NameToPageTemplateConverter : IValueConverter
      {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            switch ((string)value)
            {
                case "Page1":
                    return new DataTemplate(typeof(Page1));
                case "Page2":
                    return new DataTemplate(typeof(Page2));
                default:
                    throw new InvalidProgramException("Unknown page name");
            }
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
      }
    }