Mobile

Workaround for the Dotnet Maui Tabs ‘OnAppearing’ event

Tabs in dotnet maui have an ‘OnAppearing’ event which you would expect to be called each time a tab is activated. This however is not the case and a possible workaround is to initialize data in a static manner and pass arguments using the ‘Arguments’-construct like shown in this post :

Tab1:

<!--?xml version="1.0" encoding="utf-8" ?-->
<contentpage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:class="MauiApp1.Pages.Tab1" xmlns:local="clr-namespace:MauiApp1.Data" title="Tab1">

	<contentpage.bindingcontext>
		<local:itemviewmodel>
			<x:arguments>
				<x:int32>10</x:int32>
			</x:arguments>
		</local:itemviewmodel>
	</contentpage.bindingcontext>

	<verticalstacklayout>
		<label text="Integers as argument">
		<collectionview x:name="collectionView" margin="5" itemtemplate="{StaticResource DataTemplate1}" itemssource="{Binding ItemCollection}" selectionmode="Single">
	</collectionview></label></verticalstacklayout>

</contentpage>

Tab2:

<!--?xml version="1.0" encoding="utf-8" ?-->
<contentpage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:class="MauiApp1.Pages.Tab2" xmlns:local="clr-namespace:MauiApp1.Data" title="Tab2">

	<contentpage.bindingcontext>
		<local:itemviewmodel>
			<x:arguments>
				<x:int32>20</x:int32>
			</x:arguments>
		</local:itemviewmodel>
	</contentpage.bindingcontext>

	<verticalstacklayout>
		<label text="Integers as argument">
		<collectionview x:name="collectionView" margin="5" itemtemplate="{StaticResource DataTemplate1}" itemssource="{Binding ItemCollection}" selectionmode="Single">
	</collectionview></label></verticalstacklayout>

</contentpage>

Tab3:

<!--?xml version="1.0" encoding="utf-8" ?-->
<contentpage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:class="MauiApp1.Pages.Tab3" xmlns:local="clr-namespace:MauiApp1.Data" title="Array of integers">

	<contentpage.bindingcontext>
		<local:itemviewmodel>
			<x:arguments>
				<x:array type="{x:Type x:Int32}">
					<x:int32>10</x:int32>
					<x:int32>11</x:int32>
					<x:int32>12</x:int32>
					<x:int32>13</x:int32>
					<x:int32>14</x:int32>
					<x:int32>15</x:int32>
				</x:array>
			</x:arguments>
		</local:itemviewmodel>
	</contentpage.bindingcontext>

	<verticalstacklayout>
		<label text="Array of integers as arguments">
		<collectionview x:name="collectionView" margin="5" itemtemplate="{StaticResource DataTemplate1}" itemssource="{Binding ItemCollection}" selectionmode="Single">
	</collectionview></label></verticalstacklayout>

</contentpage>

Where the Itemcollection looks like this:

public class ItemViewModel : INotifyPropertyChanged
{
	public ItemViewModel( )	{}

	public ItemViewModel( int categoryId)
	{
		this.ItemCollection = new ObservableCollection<item>( );

		for( int i = 0; i ‹ 4; i++)
		{
			this.ItemCollection.Add( new Item( ) { Name = $"V1-{categoryId}", Description = $"c{categoryId}/T1 rocks"});
		}
	}

	public ItemViewModel( int[] categoryIds)
	{
		this.ItemCollection = new ObservableCollection<item>( );

		for( int i = 0; i ‹ categoryIds.Length; i++ )
		{
			int categoryId = categoryIds[i];
			this.ItemCollection.Add( new Item( ) { Name = $"V1-{categoryId}", Description = $"c{categoryId}/T1 rocks"});
		}
	}

	public event PropertyChangedEventHandler PropertyChanged;

	protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
	{		
		ArgumentNullException.ThrowIfNull(e);
		PropertyChanged?.Invoke(this, e);
	}

	public ObservableCollection<item> ItemCollection	{ get; set; }
}

This will result in a nice flexible way of initialisation for tabs:

Integer argument
Integer argument
Array of integers as argument

An example project can be loaded from here.