roubachof / Sharpnado.Tabs

Pure MAUI and Xamarin.Forms Tabs, including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, bendable tabs...
MIT License
479 stars 62 forks source link

[MAUI] Is there any intended way to get notified if tab page is being viewed #87

Closed andyzukunft closed 1 year ago

andyzukunft commented 1 year ago

Hey all,

thank you for providing this feature plugin. I have switched my code base to Sharpnado.Tabs as I couldn't control the Tab behaviour / layout with MAUI Shell as I need to.

I am have "pages" which are being displayed in a tab bar on my Main Page.

<tabs:DelayedView x:TypeArguments="views:DashboardPage" BindingContext="{Binding DashboardViewModel}" Animate="True" UseActivityIndicator="False" />
...

Browsing the pages works just fine. However I need to refresh the data displayed on the pages. So if the user moves from Tab 1 -> Tab 2 -> Tab 1 I want to refresh the relevant data on the page. Beforehand I was refreshing the data when the page was viewed by using OnAppearing(). For most parts this is just about calling OnPropertyChanged(). This doesn't work anymore as the Tab pages are now inheriting from ContenView and not ContentPage.

I tried to inherit the page from DelayedView. Although it doesn't generate any errors my method override of LoadView() doesn't get triggered at all.

public partial class DashboardPage : DelayedView
 {
        // ...

        public override void LoadView()
        {
            Console.WriteLine("Loaded");
        }
}

This leads me to the question: how to I get "notified" if a Page / ViewModel is being viewed?

roubachof commented 1 year ago

You can use the SelectedIndex property on the ViewSwitcher or even the OnShowCommand

andyzukunft commented 1 year ago

I am actually just implemented a test behaviour using the SelectedIndex. In my opinion this is a little bit of a hack as one needs to manually map the index to the view model? Can you elaborate on OnShowCommand?

roubachof commented 1 year ago

I see no issue to bind SelectedIndex to the vm. OnShowComand is a property of the view switcher called each time a view is shown

andyzukunft commented 1 year ago

I implemented the behaviour by using OnShowCommand however this behaviour is basically identical to the index-property (no wonder you call it from your index changed event).

Sadly both solutions don't work for me. I implemented a "More" button which shows a popup with a selection of actions (Pages to go to). When a page is being navigated to and later returns to the "main page tab view" the visible page is not being "refreshed" as I want it to.

I think my solution must work with my custom navigation handler which should force some action on the main page if I pop back to the navigation root. I will look into that.

Thanks for your time. I will close this issue within a couple of days.

Example for reference:

<tabs:ViewSwitcher x:Name="Switcher" Grid.Row="0" Margin="0" Animate="True" SelectedIndex="{Binding SelectedViewModelIndex}" OnShowCommand="{Binding ViewTabCommand}">
<!-- ... -->
</tabs:ViewSwitcher>

<tabs:DelayedView x:TypeArguments="views:DashboardPage" BindingContext="{Binding DashboardViewModel}" Animate="True" UseActivityIndicator="False" />
public Command<object> ViewTabCommand {  get; set;  }

public MainViewModel() : base()
{
    ViewTabCommand = new Command<object>(async (param) => await OnViewTabExecute(param));
}

private async Task OnViewTabExecute(object param)
{
    try
    {
        var viewIndex = (int)param;
        switch (viewIndex)
        {
            case 0: DashboardViewModel.RefreshData(); break;

            default: break;
        }
    }
    catch (Exception ex)
    {
         Log.Error(ex, $"Failed to handle tab viewing. Error = {ex}");
    }
}
andyzukunft commented 1 year ago

I corrected my behaviour by adding the OnAppearing() method to my MainPage.xaml.cs.

// MainPage.xaml.cs
protected override void OnAppearing()
{
    if (FirstLoad)
    {
         FirstLoad = false;
         return;
    }
    _ = ViewModel.RefreshActiveTab();
}

// MainPageViewModel
internal async Task RefreshActiveTab()
{
    await RefreshTab(SelectedViewModelIndex); // Method accesses tab entry based on the ViewModel/Page Index
}