0

I'm working on a .Net MAUI shell application project where I have a shell with multiple tabs in the logbook flyout. The requirement is for each tab to display a different set of log entries, for example, 'all' log entries or only those log entries created in the past 24 hours.

I have been trying to execute a RelayCommand in my MainPageViewModel whenever a tab is selected. The functionality of the RelayCommand is to update the log entries based on the selected route. However, I'm facing an issue where the BindingContext is always null when the OnShellNavigating event is fired, causing the TabSelectedCommand to never be executed. Here's my code:

AppShell.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:sys="clr-namespace:System;assembly=netstandard"
    xmlns:views="clr-namespace:Logbook.Views"
    xmlns:viewModel="clr-namespace:Logbook.ViewModels"
    xmlns:behaviors="clr-namespace:Logbook.Behaviours"
    x:Class="Logbook.AppShell"
    x:Name="shell">

    <FlyoutItem Title="Logbook" >
        <FlyoutItem.Icon>
            <FontImageSource FontFamily="FASolid"
                             Color="{AppThemeBinding 
                                    Dark ={StaticResource White}, 
                                    Light={StaticResource Gray500}}"
                             Glyph="{StaticResource fa_Book}"/>
        </FlyoutItem.Icon>
        <Tab Title="Past 24 Hours">
            <Tab.Icon>
                <FontImageSource FontFamily="FASolid"
                                 Color="{AppThemeBinding 
                                        Dark ={StaticResource White}, 
                                        Light={StaticResource Gray100}}"
                                 Glyph="{StaticResource fa_Clock}"/>
            </Tab.Icon>
            <ShellContent ContentTemplate="{DataTemplate views:MainPage}"
                          Route="MainPage\Past24Hours">
            </ShellContent>
        </Tab>
        <Tab Title="All Entries">
            <Tab.Icon>
                <FontImageSource FontFamily="FASolid"
                                 Color="{AppThemeBinding 
                                        Dark ={StaticResource White}, 
                                        Light={StaticResource Gray100}}"
                                 Glyph="{StaticResource fa_BookOpen}"/>
            </Tab.Icon>
            <ShellContent ContentTemplate="{DataTemplate views:MainPage}" 
                          Route="MainPage">
            </ShellContent>
        </Tab>
    </FlyoutItem>

MainPageViewModel.cs

public partial class MainPageViewModel : BaseViewModel
{
    // ...

    [RelayCommand]
    async Task TabSelectedAsync(string route)
    {
        // Filter the log entries by the selected route
        // ...
    }

    // ...
}

When I select a tab, the OnShellNavigating event handler in my TabSelectedBehavior is triggered, but the BindingContext in the MainPageViewModel is always null. As a result, the TabSelectedCommand is never executed.

namespace Logbook.Behaviours;
public class TabSelectedBehavior : Behavior<Shell>
{
    protected override void OnAttachedTo(Shell shell)
    {
        base.OnAttachedTo(shell);
        shell.Navigating += OnShellNavigating;
    }

    protected override void OnDetachingFrom(Shell shell)
    {
        shell.Navigating -= OnShellNavigating;
        base.OnDetachingFrom(shell);
    }

    private void OnShellNavigating(object sender, ShellNavigatingEventArgs e)
    {
        if (e.Target?.Location.OriginalString != null)
        {
            // Get the route from the navigation event
            var route = e.Target.Location.OriginalString;
            // Invoke the command in the view model passing the route as a command parameter
            if (BindingContext is MainPageViewModel viewModel && viewModel.TabSelectedCommand.CanExecute(route))
            {
                viewModel.TabSelectedCommand.Execute(route);
            }
        }
    }
}

I've tried different approaches, but the issue persists.

Can anyone suggest how can I ensure that the BindingContext is set correctly and not null when the TabSelectedCommand is executed?

Any help or guidance would be greatly appreciated. Thank you!

cramar
  • 124
  • 1
  • 16

1 Answers1

0

The BindingContext you are referring to is actually the BindingContext property of the TabSelectedBehavior class. And you didn't assign a value to it originally, so it's null.

You can put the logic from the TabSelectedAsync method into the OnNavigating method:

public partial class AppShell : Shell
    {
        public AppShell()
        {
            InitializeComponent();
        }
        protected override void OnNavigating(ShellNavigatingEventArgs args)
        {
            base.OnNavigating(args);
            if (args.Target?.Location.OriginalString != null)
            {
                // Filter the log entries by the selected route
                // ...
            }
        }
    }
Jianwei Sun - MSFT
  • 2,289
  • 1
  • 3
  • 7