My main page uses a TabbedPage
to group existing news into different lists. The tabs aren't fixed; they're built from a data binding operations against a collection that's retried through a web service call.
I'd like to persist the selected tab across activity restarts, but it seems like I'm missing something. Since there's no selected tab property (which can be set through data binding), I've tried to handle the PageChanged
and the CurrentPageChangedCommand
events. I'm using the PageChanged
to set the selected tab to the previous selected tab and the CurrentPageChangedCommand
is being used to update the persisted selected tab (I'm using the Application.Properties
to make sure the selected tab survives app restarts).
Unfortunately, the events generated by the tab will always set tab 0 as the selected tab! Here's what I'm seeing (let's assume that my app was killed white tab 3 was active):
TabbedPage.ItemsSource
property, the tab will automatically fire the CurrentPageChangedCommand
, passing the first tab (tab at position 0).Properties
dictionary. So now, instead of 3 (which was the value persisted when my app was killed), it will have 0.PagesChanged
Properties
dictionary, it will get the default tab (0) and not 3. This happens because the CurrentPageChangedCommand
was fired before the PagesChanged
event (step 2), completely overriding the previously persisted tab index.This default behaviour will also give a bad user experience when the user refreshes the current list (pull to refresh) because he always ends up seeing tab 0 list.
So, any clues on how to solve this? How have you guys solved this?
Thanks.
It seems it can't be achieved using MVVM as CurrentPage
is not a bindable property and CurrentPageChanged
is an event.
However, there's no need to handle the PagesChanged
event. You could record the index in the changed event like:
private void MyTabbedPage_CurrentPageChanged(object sender, EventArgs e)
{
Application.Current.Properties["index"] = this.Children.IndexOf(CurrentPage);
Application.Current.SavePropertiesAsync();
}
Then you could set your tabbed page's current page after you have loaded all the tabs:
object index;
Application.Current.Properties.TryGetValue("index", out index);
if (index != null)
{
CurrentPage = Children[int.Parse(index.ToString())];
}
// Subscribe the event
CurrentPageChanged += MyTabbedPage_CurrentPageChanged;
I placed the code above in the custom tabbed page's constructor and it could change the selected tab at initial time.
Update:
If you want to change the tabbed page's children dynamically, you could define a property to avoid the event being fired when you change the children:
bool shouldChangeIndex = true;
private void MyTabbedPage_CurrentPageChanged(object sender, EventArgs e)
{
if (shouldChangeIndex)
{
var index = this.Children.IndexOf(CurrentPage);
Application.Current.Properties["index"] = index;
Application.Current.SavePropertiesAsync();
}
}
// Simulate the adjusting
shouldChangeIndex = false;
Children.Clear();
Children.Add(new MainPage());
Children.Add(new SecondPage());
shouldChangeIndex = true;
object index;
Application.Current.Properties.TryGetValue("index", out index);
if (index != null)
{
CurrentPage = Children[int.Parse(index.ToString())];
}