Xamarin Forms:在 activity 重新启动后保持选定的选项卡

Xamarin Forms: maintain selected tab over activity restarts

我的主页使用 TabbedPage 将现有新闻分组到不同的列表中。选项卡不是固定的;它们是根据针对通过 Web 服务调用重试的集合的数据绑定操作构建的。

我想在 activity 重新启动后保留选定的选项卡,但我似乎遗漏了什么。由于没有选定的选项卡 属性(可以通过数据绑定设置),我尝试处理 PageChangedCurrentPageChangedCommand 事件。我正在使用 PageChanged 将选定的选项卡设置为之前选定的选项卡,并且 CurrentPageChangedCommand 用于更新持久化的选定选项卡(我正在使用 Application.Properties 来确保所选标签在应用重启后仍然存在)。

不幸的是,选项卡生成的事件将始终将选项卡 0 设置为所选选项卡!这是我所看到的(假设我的应用程序已被终止,而白色选项卡 3 处于活动状态):

  1. 当数据绑定到 TabbedPage.ItemsSource 属性 时,选项卡将自动触发 CurrentPageChangedCommand,传递第一个选项卡(位置 0 处的选项卡)。
  2. 我的代码处理该事件并通过更改 Properties 字典中的选定选项卡来更新当前持久化的选定选项卡。所以现在,它不再是 3(这是我的应用程序被终止时保留的值),而是 0。
  3. 然后该选项卡将触发 PagesChanged
  4. 当我的代码处理这个事件时,它会尝试更新选定的选项卡。但是,当它从 Properties 字典访问选定的选项卡时,它将获得默认选项卡 (0) 而不是 3。发生这种情况是因为 CurrentPageChangedCommandPagesChanged 事件之前触发 (步骤 2),完全覆盖之前保留的选项卡索引。

当用户刷新当前列表(拉动刷新)时,这种默认行为也会带来糟糕的用户体验,因为他最终总是看到选项卡 0 列表。

那么,关于如何解决这个问题有什么线索吗?你们是怎么解决这个问题的?

谢谢。

不幸的是,我不得不放弃 MVVM 方法...最后,我不得不求助于代码和几个标志来控制何时应处理生成的选项卡事件。

似乎无法使用 MVVM 实现,因为 CurrentPage 不是可绑定的 属性 并且 CurrentPageChanged 是一个事件。

但是,没有必要处理 PagesChanged 事件。您可以在更改的事件中记录索引,例如:

private void MyTabbedPage_CurrentPageChanged(object sender, EventArgs e)
{
    Application.Current.Properties["index"] = this.Children.IndexOf(CurrentPage);
    Application.Current.SavePropertiesAsync();
}

加载完所有标签后,您可以设置标签页的当前页:

object index;
Application.Current.Properties.TryGetValue("index", out index);
if (index != null)
{
    CurrentPage = Children[int.Parse(index.ToString())];
}
// Subscribe the event
CurrentPageChanged += MyTabbedPage_CurrentPageChanged;

我将上面的代码放在自定义标签页的构造函数中,它可以在初始时更改所选标签。

更新:

如果您想动态更改标签页的子项,您可以定义一个 属性 以避免在更改子项时触发事件:

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())];
}