xamarin / XamarinCommunityToolkit

The Xamarin Community Toolkit is a collection of Animations, Behaviors, Converters, and Effects for mobile development with Xamarin.Forms. It simplifies and demonstrates common developer tasks building iOS, Android, and UWP apps with Xamarin.Forms.
MIT License
1.59k stars 471 forks source link

[Bug][iOS] Binding to TabView.SelectedIndex cause that TabView doesn't work #979

Open SeRgI1982 opened 3 years ago

SeRgI1982 commented 3 years ago

Description

I would like to have a chance preselect different TabItem than the first on when navigate to page with TabView. Unfortunately, it doesn't work when you bind SelectedIndex to your ViewModel and set a proper index inside ViewModel. The control stops working - there is no chance to navigate to different TabItems when this Binding exists.

Steps to Reproduce

  1. Create Page with TabView and a few TabViewItem's
  2. Bind TabView.SelectedIndex to your ViewModel.SelectedTabIndex
  3. Try to set ViewModel.SelectedTabIndex to correct value

Expected Behavior

TabView will navigate automatically to an appropriate TabViewItem

Actual Behavior

On iOS TabView stuck - there is no chance to navigate to other tabs - even by tapping other TabViewItem icons. It worked in version 1.0.0

Basic Information

Sample app below:

TabViewTest.zip

Cfun1 commented 3 years ago

Seems the same issue as https://github.com/xamarin/XamarinCommunityToolkit/issues/870 isn't supposed to be fixed @jfversluis ?

jfversluis commented 3 years ago

@jsuarezruiz

Kapusch commented 3 years ago

Actually, I can provide the same comment as for #1012

I also have noticed this bug many times, but I cannot say why exactly. Anytime I sign out / sign in again to my app, then I can see my tab well positioned on the value I have initialized in the ViewModel.

In my XAML file, the property binding is set as followed :

        SelectedIndex="{Binding SelectedTopTabsIndex, Mode=TwoWay}"

And the value is configured in the ViewModel as followed :

        private int _selectedTopTabsIndex = 1;
        public int SelectedTopTabsIndex
        {
            get => _selectedTopTabsIndex;
            set
            {
                _selectedTopTabsIndex = value;
                RaisePropertyChanged(() => SelectedTopTabsIndex);
            }
        }

I guess it could be something related to events ordering, BindingContext initializations... I'll comment more in case I get it.

Kapusch commented 3 years ago

TL;DR;

Check about your async methods which occured before your BindingContext is initialized !


I know that's not a concrete indication, but I guess this could help to understand the source of this issue.

In my case, it was clearly about async methods. Indeed, I have a NavigationService which navigates from page to page thanks to async method. And actually, once I sign in to my app, the async method for navigating to the MainView works fine.

But if I restart the app, and I am still authenticated, the NavigationService redirects me directly to the MainView. And this is where the Tabs are not well initialized, probably because OnResume / OnStart methods from "App.xaml.cs" are not async ?

I don't know, but the first thing I've tried by chance was to add this delay task in the NavigationService initialization, and everything worked properly...

            await Task.Delay(1);

But I have continued to investigate. I have a platform-specific implementation for the Firebase RemoteConfig service, which I call every time the application starts. And methods I call in this service are async. What I did is calling .Wait() method to the last awaitable Task, and it fixed all my issues.

                long cacheExpiration = 3600; // 1 hour in seconds.

                //Fetch remote values
                var status = await RemoteConfig.SharedInstance.FetchAsync(cacheExpiration);
                if (status == RemoteConfigFetchStatus.Success)
                {
                    //Activate new values
                    RemoteConfig.SharedInstance.ActivateAsync().Wait();
                }
vecalion commented 3 years ago

We're also experiencing this bug. Here is minimal repro changes: https://github.com/vecalion/XamarinCommunityToolkit/commit/829479e01a2a568b8f81488976f824b7fad88623 (Start the sample project -> Views -> TabView -> Getting Started)

Here is a video demonstration: https://1drv.ms/v/s!AvwfTJGXo3Kxg5oX-HRPnqZKynvh-g?e=AchHNL notice that the index is indefinitely changed from 0 to 1 and back to 0

@jfversluis, @jsuarezruiz I believe the issue was introduced in this changeset: https://github.com/xamarin/XamarinCommunityToolkit/commit/3abf5fa7eeaa29e76e9b1bfeb17575b75bccc799

InquisitorJax commented 3 years ago

... just to mention a work-around: I am still able to use swiping to access the tabs, but the tab selection for a particular tab becomes unresponsive.

bricefriha commented 3 years ago

Hi everyone, If this can helps, I'm facing the same issue. However, I'm not binding TabView.SelectedIndex. It works perfectly with Android but not with iOS.

I hope this will help you 😉

LeoJHarris commented 3 years ago

We're also experiencing this bug. Here is minimal repro changes: vecalion@829479e (Start the sample project -> Views -> TabView -> Getting Started)

Here is a video demonstration: https://1drv.ms/v/s!AvwfTJGXo3Kxg5oX-HRPnqZKynvh-g?e=AchHNL notice that the index is indefinitely changed from 0 to 1 and back to 0

@jfversluis, @jsuarezruiz I believe the issue was introduced in this changeset: 3abf5fa

Puling the community toolkit and reverting the changes resolves the issue. @jfversluis @jsuarezruiz can we revert these changes? Seems to resolve the issue with toggling the tab view items

luwei888 commented 2 years ago

same problem,how to fix ?

Kapusch commented 2 years ago

A possible workaround is to set the SelectedIndex in the view "OnAppearing" event (for ContentPage views only).

LeoJHarris commented 2 years ago

@Kapusch

Try this as a work around

 <xct:TabView
        SelectedIndex="{Binding SelectedTabViewIndex, Mode=TwoWay}">
        <xct:TabView.TabIndicatorView>
            <BoxView WidthRequest="{Binding Source={x:Reference tabItemBase}, Path=Width}" />
        </xct:TabView.TabIndicatorView>
        <xct:TabViewItem
            x:Name="tabItemBase"
nk-alex commented 1 year ago

Any update on this topic? Still not working for me on version 2.0.5