Skip to content

Updating a ControlTemplate at runtime causes it to disappear.  #15649

@widavies

Description

@widavies

Description

I'm trying to implement a very simple tabbed view. My approach is to use ControlTemplate on the containing ContentPage and update this dynamically to whatever tab is active. I can't use TabbedPage because I'm using Shell.

Here's a very minimal example. There are two tabs with the text "TAB 1" and "TAB 2" respectively. Tapping either button at the top should take you to the corresponding tab.

image

However, when the Tab2 button is pressed, instead of the tab changing, the tab remains the same and the buttons disappear (the buttons are displayed through a ContentPresenter within each tab):

image

This issue seems to be pretty similar, so potentially the fix merged there could apply here as well?

Steps to Reproduce

To reproduce this issue, make the following changes to the built-in Maui.Controls.Sample project:

Replace the contents of maui\src\Controls\samples\Controls.Sample\Pages\MainPage.xaml with:

<views:BasePage
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:sys="clr-namespace:System;assembly=netstandard"
    x:Class="Maui.Controls.Sample.Pages.MainPage"
    xmlns:views="clr-namespace:Maui.Controls.Sample.Pages.Base"
    xmlns:local="clr-namespace:Maui.Controls.Sample"
    x:Name="HomePage"
    NavigationPage.IconColor="White"
    ControlTemplate="{DynamicResource Tab1}"
    Title="Gallery">
    <ContentPage.Resources>
        <ResourceDictionary>
            <ControlTemplate x:Key="Tab1">
                <StackLayout>
                    <ContentPresenter />
                    <Label>TAB 1</Label>
                    
                </StackLayout>
            </ControlTemplate>
            <ControlTemplate x:Key="Tab2">
                <StackLayout>
                    <ContentPresenter />
                    <Label>TAB 2</Label>
                </StackLayout>

            </ControlTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Triggers>
        <DataTrigger TargetType="ContentPage"
                     Binding="{Binding PositionSelected, Source={x:Reference HomePage}}"
                     Value="1">
            <Setter Property="ControlTemplate" Value="{DynamicResource Tab1}" />
        </DataTrigger>
        <DataTrigger TargetType="ContentPage"
                     Binding="{Binding PositionSelected, Source={x:Reference HomePage}}"
                     Value="2">
            <Setter Property="ControlTemplate" Value="{DynamicResource Tab2}" />
        </DataTrigger>
    </ContentPage.Triggers>
    <StackLayout>
        <Button Text="Tab1"
                Command="{Binding TabCommand, Source={x:Reference HomePage}}"
                HeightRequest="50"
                CommandParameter="1">
        </Button>
        <Button Text="Tab2"
                Command="{Binding TabCommand, Source={x:Reference HomePage}}"
                HeightRequest="50"
                CommandParameter="2">
        </Button>
    </StackLayout>
</views:BasePage>

Make the following adjustments to C:\Users\WillD\Desktop\maui\src\Controls\samples\Controls.Sample\Pages\Base\BasePage.cs:

	public class BasePage : ContentPage
	{
		SectionModel _selectedItem;

+		public int _positionSelected = 0;
+
+		public int PositionSelected
+		{
+			set
+			{
+				if (_positionSelected != value)
+				{
+					_positionSelected = value;
+
+					OnPropertyChanged();
+				}
+			}
+			get => _positionSelected;
+		}
+
+		public ICommand TabCommand { get; }

		public BasePage()
		{
			Application.Current.Resources.TryGetValue("LightBackgroundColor", out object lightBackgroundResource);
			Application.Current.Resources.TryGetValue("DarkBackgroundColor", out object darkBackgroundResource);

			if (lightBackgroundResource is Color lightBackgroundColor && darkBackgroundResource is Color darkBackgroundColor)
				this.SetAppThemeColor(BackgroundColorProperty, lightBackgroundColor, darkBackgroundColor);

			NavigateCommand = new Command(async () =>
			{
				if (SelectedItem != null)
				{
					if (Application.Current.MainPage is FlyoutPage fp)
						await fp.Detail.Navigation.PushAsync(PreparePage(SelectedItem));
					else
						await Navigation.PushAsync(PreparePage(SelectedItem));

					SelectedItem = null;
				}
			});

+			TabCommand = new Command<string>((param) => PositionSelected = int.Parse(param));

Link to public reproduction project repository

widavies@66b4285

Version with bug

7.0.86

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android API 34

Did you find any workaround?

No response

Relevant log output

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-layoutStackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenteri/great-reporterThis issue is opened by an author who is known to open high-quality issuesplatform/androidt/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions