Модель навигации (C#/VB/C++ и XAML)

Для приложений Магазина Windows на XAML рекомендуется модель навигации, используемая в шаблонах проектов "Приложение-концентратор", "Приложение таблицы" и "Приложение с разделением". Эта модель создает центральный фрейм как содержимое окна по умолчанию, и пользователи переходят на другие страницы с помощью этого фрейма. Модель навигации с одним фреймом обеспечивает плавный, как в приложении, переход между страницами, а также упрощает управление состоянием программы. Дополнительные сведения о навигации и пример использования встроенной навигации в приложении Магазина Windows на XAML см. в разделе Краткое руководство: использование одностраничной навигации.

Важно  Информация в этой теме обновлена для Microsoft Visual Studio 2013.

Файл App.xaml.cs/vb/cpp создает Frame, если он еще не существует, и делает Frame содержимым текущего окна. Если содержимое фрейма имеет нулевое значение, приложение переходит на домашнюю страницу, как указано в коде App.xaml. Например, в приложении таблицы код выглядит следующим образом: rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups") ).

Во время установки SuspensionManager регистрирует Frame. SuspensionManager — это класс поддержки, расположенный в общей папке шаблона "Приложение таблицы" или "Приложение с разделением", который предоставляет реализацию, используемую для хранения и загрузки состояния после завершения работы приложения.

Все приложения проходят жизненный цикл приложения, определяемый операционной системой. Всякий раз, когда работа приложения завершается системой по какой-либо причине, например ограничения, завершение работы, перезагрузка и т. д., разработчик должен восстановить данные после возобновления работы приложения. Для этого можно использовать SuspensionManager.

SuspensionManager записывает глобальное состояние сеанса для упрощения процесса управления жизненным циклом приложения. Состояние сеанса автоматически сбрасывается при различных условиях, и его следует использовать только для хранения сведений, которые должны удобно передаваться между сеансами, но которые необходимо удалять в случае сбоя или обновления приложения. Обычно к ним относятся данные промежуточного пользовательского интерфейса.

SuspensionManager имеет два свойства: SessionState и KnownTypes.

  • SessionState предоставляет доступ к глобальному состоянию текущего сеанса. Это состояние сериализуется методом SaveAsync и восстанавливается методом RestoreAsync. Все данные сохраняются и восстанавливаются с помощью DataContractSerialization; данные должны быть максимально сжаты. Настоятельно рекомендуется использовать строки — другой тип автономных данных.
  • KnownTypes хранит список пользовательских типов, предоставленных для DataContractSerializer, который используется методами SaveAsync и RestoreAsync при чтении и записи состояния сеанса. Дополнительные типы изначально пустые, и их можно добавить для настройки процесса сериализации.

SuspensionManager хранит состояние в словаре, SessionState. FrameState хранится в словаре согласно ключу, который уникально привязывается к Frame. В каждом словаре FrameState хранится состояние каждой страницы в состоянии навигации для конкретного фрейма. На каждой странице хранится параметр навигации и любое другое состояние, которое решает добавить пользователь.

Это работает следующим образом: при создании Frame, если требуется хранить состояние для данного фрейма, его необходимо сразу же зарегистрировать. Фреймы регистрируются путем вызова (SuspensionManager.RegisterFrame(rootFrame, "AppFrame")). Каждый фрейм должен иметь уникальный ключ, связанный с ним. Обычно большинство приложений имеют только один фрейм. Если объявляется второй фрейм, его также необходимо зарегистрировать. После регистрации фрейма в нем задается два присоединенных свойства. Первое свойство — это ключ, связанный с фреймом, второе свойство — словарь состояния сеанса, который будет связан с фреймом. Для фреймов, зарегистрированных ранее, сразу же восстанавливается навигация и состояние. Кроме того, можно отменить регистрацию фреймов, при этом состояние навигации и журнал будут удалены.

Теперь рассмотрим важные вызовы: SaveAsync и RestoreAsync. SaveAsync используется для сохранения всего SessionState. Все фреймы, зарегистрированные с помощью SuspensionManager.RegisterFrame, также сохраняют текущий стек навигации, который в свою очередь предоставляет активным страницам возможность сохранять данные. Затем SessionState сериализуется с помощью DataContractSerializer и записывается в файл, который хранится в локальной папке, как определено в ApplicationData.

RestoreAsync используется для чтения ранее сохраненных SessionState. Все фреймы, зарегистрированные с помощью RegisterFrame, также восстанавливают предыдущий стек навигации, который предоставляет активной странице возможность восстановить состояние. Также как в случае SaveAsync, DataContractSerializer используется для десериализации состояния, хранимого в файле в локальной папке приложения.

Существуют две распространенные ошибки, которые совершают пользователи, пытаясь сохранить состояние приложения.

  • Типы, хранимые отдельными страницами, должны поддерживать сериализацию с помощью DataContractSerializer на C# и VB. Для этого любые пользовательские типы необходимо зарегистрировать, чтобы их можно было сохранить или восстановить. SuspensionManager предоставляет коллекцию KnownTypes, которая передает типы из коллекции в DataContractSerializer. Поскольку SuspensionManager вызывается для восстановления состояния в переопределении OnLaunched кода App.xaml, типы рекомендуется регистрировать в конструкторе приложений.

            public App()
            {
                this.InitializeComponent();
                this.Suspending += OnSuspending;
                SuspensionManager.KnownTypes.Add(typeof(MyCustomType));
            }
    
  • Параметры, переданные во время навигации, должны поддерживать сериализацию с помощью платформы. При сохранении и восстановлении стека навигации вызывается Frame.GetNavigationState() и Frame.SetNavigationState(). Оба вызова используют внутренний формат сериализации, и все типы, переданные как параметр в Frame.Navigate(), должны поддерживать сериализацию с помощью платформы.

Использование SuspensionManager заключается в реализации NavigationHelper.

NavigationHelper как реализация страницы, на которой предоставляются следующие важные возможности.

  • Обработчики событий для GoBack, GoForward и GoHome.
  • Мышь и сочетания клавиш для навигации.
  • Управление состоянием для навигации и управление жизненным циклом процесса.

Модель представления по умолчанию

DefaultViewModel используется в каждом шаблоне элемента сложной страницы. DataContext привязан к DefaultViewModel, определенному на самой странице: DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}". Свойство DefaultViewModel принадлежит к типу ObservableDictionary, который является картой строк (ключей) для объектов (значений). DefaultViewModel предоставляется для удобства, и при необходимости его можно изменить на строго типизированную модель представления.

Затем каждая страница привязывается к свойствам, которые задаются в DefaultViewModel в коде. Например, рассмотрим GroupedItemsPage. На этой странице CollectionViewSource имеет исходное свойство, привязанное к свойству Groups (Source="{Binding Groups}". Groups — это ключ пары "ключ-значение", хранимой в DefaultViewModel (this.DefaultViewModel["Groups"] = sampleDataGroups;).

Состояние представления приложений для визуального сопоставления состояний

В шаблонах для Windows 8 LayoutAwarePage предоставлял код для обработки состояния просмотра, но этот код не является обязательным для Windows 8.1. Только страницы SplitPage и FileOpenPicker включают код для обработки состояния просмотра. Теперь от каждой страницы ожидается обработка всех размеров окон, ширина которых составляет не менее 500 пикселей.

Навигация

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

NavigationHelper также регистрирует общие действия мыши и сочетания клавиш, которые обычно используются для навигации. Кнопка мыши для перехода назад, "ALT + клавиша со стрелкой влево" и клавиша "Предыдущий" используются для перехода назад. Кнопка мыши для перехода вперед, "ALT + клавиша со стрелкой вправо" и клавиша "Следующий" используются для перехода вперед.

Управление жизненным циклом процесса

Помимо предоставления реализаций, описанных выше, NavigationHelper также необходимо вызывать из OnNavigatedTo() и обработчиков событий OnNavigatedFrom(), реализованных на каждой из страниц. Когда эти события происходят, NavigationHelper вызывает реализацию LoadState() и SaveState() для конкретной страницы. Реализацию этих функций можно настроить на каждой из страниц. Их следует использовать вместо OnNavigatedTo() и OnNavigatedFrom() соответственно.

OnNavigatedFrom() вызывается, если необходимо отобразить страницу в Frame. При переходе на новую страницу загружается состояние, связанное с ней. Если страница восстанавливается, восстанавливается состояние, сохраненное ранее. Затем вызывается LoadState, чтобы каждая страница могла отреагировать. LoadState имеет два параметра: исходный параметр навигации, переданный в OnNavigatedTo, и предыдущее состояние страницы, если имеется.

OnNavigatedFrom() вызывается, если страницу больше не требуется отображать в Frame. При переходе со страницы разрешается сохранить ее текущее состояние. Пустой словарь передается в SaveState(). Каждая страница может переопределить SaveState и сохранить объекты в словаре с ключом (строка в объект). Затем этот словарь связывается со страницей и добавляется в SessionState, который отслеживается SuspensionManager для данного фрейма.

Примечание  

  • Все данные, хранимые на отдельной странице, должны быть доступны для сериализации с помощью DataContractSerializer. Дополнительные сведения см. в описании SuspensionManager в начале этого раздела.
  • Кроме того, здесь важно сохранять только сведения промежуточного пользовательского интерфейса, поскольку это состояние будет потеряно, если приложение будет закрыто каким-либо способом, отличным от завершения работы.

Структура приложения

Чтобы понять структуру приложения, рассмотрим приложение, созданное с помощью шаблона проекта "Приложение таблицы". Начальной точкой всех приложений Магазина Windows, использующих XAML, является объект приложения в App.xaml и связанный с ним код программной части. Первым кодом, который выполняется при создании приложения, является конструктор приложений. Затем вызывается один из множества методов активации, в данном случае событие OnLaunched после запуска приложения через плитку на начальном экране. При этом создается Frame, повторно загружается любое предыдущее состояние (если работа приложения была ранее завершена) и используется фрейм для перехода на первую страницу. При переходе на страницу обработчик событий OnNavigatedTo на странице вызывает NavigationHelper. NavigationHelper запускает и записывает параметры, а также повторно загружает сведения о любом предыдущем состоянии для данной страницы. Затем он вызывает метод LoadState(), который переопределяется в GroupedItemsPage. Данные загружаются, и заполняется модель представления по умолчанию. При переходе на другую страницу обработчик событий OnNavigatedFrom вызывает NavigationHelper, который сохраняет любое состояние данной страницы, вызвав SaveState(). SaveState() переопределяется на страницах с состоянием промежуточного пользовательского интерфейса, например SplitPage, до перехода на новую страницу и повторного вызова метода LoadState().

Связанные разделы

Шаблоны проектов на C#, VB и C++ для приложений из Магазина Windows

Часть 2. Управление жизненным циклом и состоянием приложения

Часть 3. Навигация, макет и представления