Xamarin Forms: сохранить выбранную вкладку при перезапуске активности

На моей главной странице используется TabbedPage, чтобы сгруппировать существующие новости в разные списки. Вкладки не зафиксированы; они построены на основе операций привязки данных к коллекции, которая повторяется через вызов веб-службы.

Я хотел бы сохранить выбранную вкладку при перезапуске активности, но мне кажется, что я что-то упускаю. Поскольку нет свойства selected tab (которое можно установить с помощью привязки данных), я попытался обработать события PageChanged и CurrentPageChangedCommand. Я использую PageChanged для установки выбранной вкладки на предыдущую выбранную вкладку, а CurrentPageChangedCommand используется для обновления сохраненной выбранной вкладки (я использую Application.Properties, чтобы убедиться, что выбранная вкладка сохраняется после перезапуска приложения).

К сожалению, события, генерируемые этой вкладкой, всегда устанавливают вкладку 0 как выбранную! Вот что я вижу (предположим, что мое приложение было убито, активна белая вкладка 3):

  1. Когда данные привязаны к свойству TabbedPage.ItemsSource, вкладка автоматически запускает CurrentPageChangedCommand, передавая первую вкладку (вкладка в позиции 0).
  2. Мой код обрабатывает событие и обновляет текущую сохраняемую выбранную вкладку, изменяя выбранную вкладку в словаре Properties. Итак, теперь вместо 3 (это значение сохранялось, когда мое приложение было убито), у него будет 0.
  3. Затем вкладка запустит PagesChanged
  4. Когда мой код обрабатывает это событие, он попытается обновить выбранную вкладку. Однако, когда он обращается к выбранной вкладке из словаря Properties, он получает вкладку по умолчанию (0), а не 3. Это происходит потому, что CurrentPageChangedCommand был запущен до события PagesChanged (шаг 2), полностью переопределив ранее сохраненный индекс вкладки.

Это поведение по умолчанию также ухудшит работу пользователя, когда пользователь обновит текущий список (потяните, чтобы обновить), потому что он всегда видит список табуляции 0.

Итак, есть какие-нибудь подсказки о том, как решить эту проблему? Как вы, ребята, это решили?

Спасибо.


person Luis Abreu    schedule 29.05.2019    source источник


Ответы (2)


Кажется, этого нельзя достичь с помощью 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())];
}
person Anonymous    schedule 30.05.2019
comment
Проблема в том, что вкладки инициализируются после конструктора и могут обновляться несколько раз после первого рендеринга ... кстати, также была раздражающая мерцающая штука ... поэтому я заменил код привязки на жду модель просмотра, и теперь я создаю страницы вручную, так что я могу установить выбранную страницу во время строительства - person Luis Abreu; 30.05.2019
comment
@LuisAbreu Вы можете вызвать приведенный выше код после обновления вкладок. Устанавливайте CurrentPage снова каждый раз, когда вы хотите загрузить новые вкладки. - person Anonymous; 30.05.2019
comment
Проблема в том, что событие pagechanged запускается после события currentpagechanged (это то, что я видел в своем коде) ... - person Luis Abreu; 30.05.2019
comment
@LuisAbreu Теперь я знаю вашу проблему. Пожалуйста, посмотрите мое обновление. - person Anonymous; 30.05.2019
comment
Да, это похоже на то, что я сделал (чтобы убрать раздражающие щелчки, возникающие во время повторной привязки, я обновил код, чтобы установить выбранную страницу во время рендеринга). К сожалению, это означает, что вы не можете использовать команды bindings +, и вам придется прибегнуть к написанию кода в представлении ... - person Luis Abreu; 30.05.2019

К сожалению, мне пришлось отказаться от подхода MVVM ... В конце концов, мне пришлось прибегнуть к коду и паре флагов, чтобы контролировать, когда должны обрабатываться сгенерированные события вкладки.

person Luis Abreu    schedule 30.05.2019