Потяните, чтобы обновить
Обновление путем оттягивания позволяет пользователю потянуть список данных вниз, чтобы получить дополнительные данные. Обновление путем оттягивания широко используется на устройствах с сенсорным экраном. Вы можете использовать представленные в этом разделе API-интерфейсы для реализации обновления путем оттягивания в вашем приложении.
Выбор правильного элемента управления
Используйте обновление путем оттягивания при работе со списком или сеткой с данными, которые пользователь может регулярно обновлять, и если ваше приложение предназначено для работы на устройствах, рассчитанных на сенсорное управление.
Также можно использовать RefreshVisualizer для создания согласованного обновления, вызываемого другими способами, например, с помощью кнопки "Обновить".
Обновить элементы управления
Функция "pull-to-refresh" активируется двумя элементами управления.
- RefreshContainer — ContentControl, предоставляющий оболочку для процесса обновления. Он обрабатывает сенсорные взаимодействия и управляет состоянием внутреннего визуализатора обновления.
- RefreshVisualizer — инкапсулирует визуализацию обновления, описанную в следующем разделе.
Основным элементом управления является RefreshContainer, который размещается в качестве оболочки содержимого, которое пользователь тянет для запуска обновления. RefreshContainer работает только с сенсорным экраном, поэтому мы также рекомендуем использовать кнопку "Обновить" для пользователей, у которых нет сенсорного интерфейса. Кнопку "Обновить" можно разместить в подходящем месте в приложении — на панели команд или в месте, находящемся рядом с обновляемой поверхностью.
Визуализация обновления
Визуализация обновления по умолчанию — это циклический индикатор хода выполнения, который сообщает о том, когда произойдет обновление, и о ходе обновления после его запуска. Визуализатор обновления имеет 5 состояний.
Расстояние, на которое пользователь должен оттянуть список вниз для инициации обновления, называется threshold (пороговое значение). Визуализатор State определяется состоянием оттягивания в отношении этого порогового значения. Допустимые значения находятся в перечислении RefreshVisualizerState.
Бездействие
Состоянием визуализатора по умолчанию является Idle. Пользователь не взаимодействует с RefreshContainer посредством сенсорного ввода и обновление не выполняется.
Визуальные признаки работы визуализатора обновления отсутствуют.
Взаимодействие
Когда пользователь оттягивает список в направлении, заданном свойством PullDirection, и до достижения порогового значения, визуализатор находится в состоянии Interacting.
Если пользователь отпускает элемент управления в этом состоянии, он возвращается в состояние Idle.
Визуально значок отображается как отключенный (непрозрачность 60 %). Кроме того, значок производит один полный оборот с помощью действия прокрутки.
Если пользователь оттянет список, превысив значение порогового значения, визуализатор перейдет из состояния Interacting в состояние Pending.
Визуально прозрачность значка составит 100 % и он будет меняться в размере до 150 % и возвращаться обратно до 100 % во время процесса перехода состояний.
Не завершено
Когда пользователь оттягивает список, превысив пороговое значение, визуализатор переходит в состояние Pending.
- Когда пользователь перемещает список обратно, в пределы порогового значения, не отпуская его, визуализатор переходит в состояние Interacting.
- Если пользователь отпускает список, инициируется запрос на обновление и визуализатор переходит в состояние Refreshing.
Визуально размер и непрозрачность значка составляют 100 %. В этом состоянии значок продолжает перемещаться вниз с помощью действия прокрутки, но больше не вращается.
Обновление
Когда пользователь отпускает визуализатор за пределами порогового значения, он переходит в состояние Refreshing.
При входе в это состояние возникает событие RefreshRequested. Это сигнал для запуска обновления содержимого приложения. Аргументы события (RefreshRequestedEventArgs) содержат объект Deferral, который следует использовать в обработчике событий. Затем отсрочку следует пометить как завершенную, когда код для выполнения обновления завершится.
После завершения обновления визуализатор возвращается в состояние Idle.
Визуально значок возвращается обратно в пороговое положение и вращается на протяжении процесса обновления. Это вращение используется для отображения хода выполнения обновления и заменяется анимацией входящего содержимого.
Просмотр
Когда пользователь оттягивает список в направлении обновления из начального положения, где обновление не разрешено, визуализатор переходит в состояние Peeking. Как правило, это происходит, если элемент ScrollViewer не находится в положении 0, когда пользователь начинает оттягивать список.
- Если пользователь отпускает элемент управления в этом состоянии, он возвращается в состояние Idle.
Направление оттягивания
По умолчанию пользователь оттягивает список сверху вниз, чтобы начать обновление. Если у вас есть список или сетка с другой ориентацией, следует изменить направление оттягивания, чтобы обеспечить соответствие контейнера обновления.
Свойство PullDirection принимает одно из следующих значений RefreshPullDirection: BottomToTop, TopToBottom, RightToLeft или LeftToRight.
При изменении направления вытягивания начальная позиция спиннера хода выполнения визуализатора автоматически поворачивается, чтобы стрелка начиналось в соответствующей позиции для направления вытягивания. При необходимости можно изменить свойство RefreshVisualizer.Orientation, чтобы переопределить автоматическое поведение. В большинстве случаев мы рекомендуем оставлять значение по умолчанию Auto.
UWP и WinUI 2
Внимание
Сведения и примеры в этой статье оптимизированы для приложений, использующих пакет SDK для приложений Windows и WinUI 3, но обычно применимы к приложениям UWP, использующим WinUI 2. См. справочник по API UWP для конкретных сведений и примеров платформы.
В этом разделе содержатся сведения, необходимые для использования элемента управления в приложении UWP или WinUI 2.
Элементы управления обновления для приложений UWP включены в состав WinUI 2. Дополнительные сведения, включая инструкции по установке, см. в статье WinUI 2. API для этого элемента управления существуют в пространствах имен Windows.UI.Xaml.Controls (UWP) и Microsoft.UI.Xaml.Controls (WinUI).
- API UWP: RefreshContainer, RefreshVisualizer
- Apis WinUI 2: RefreshContainer, RefreshVisualizer
- Откройте приложение коллекции WinUI 2 и просмотрите pullToRefresh в действии. Приложения из коллекции WinUI 2 включают интерактивные примеры большинства элементов управления, возможностей и функций WinUI 2. Получите приложение из Microsoft Store или получите исходный код в GitHub.
Мы рекомендуем использовать последнюю версию WinUI 2 , чтобы получить самые актуальные стили, шаблоны и функции для всех элементов управления.
Чтобы использовать код в этой статье с WinUI 2, используйте псевдоним в XAML (мы используем muxc
), чтобы представить API библиотеки пользовательского интерфейса Windows, включенные в проект. Дополнительные сведения см. в статье "Начало работы с WinUI 2 ".
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
<muxc:RefreshContainer />
Реализация обновления по запросу
- Важные API: RefreshContainer, RefreshVisualizer
Приложение коллекции WinUI 3 включает интерактивные примеры большинства элементов управления, функций и функций WinUI 3. Получение приложения из Microsoft Store или получение исходного кода на GitHub
Чтобы добавить функцию обновления путем оттягивания в список, нужно выполнить всего несколько действий.
- Перенесите список в элемент управления RefreshContainer.
- Обработайте событие RefreshRequested для обновления содержимого.
- При необходимости запустите обновление, вызвав метод RequestRefresh (например, нажатием кнопки).
Примечание.
Можно создать отдельный экземпляр RefreshVisualizer. Тем не менее мы рекомендуем переносить содержимое в RefreshContainer и использовать RefreshVisualizer, предоставляемый свойством RefreshContainer.Visualizer даже для сценариев без сенсорного ввода. В этой статье мы предполагаем, что визуализатор всегда берется из контейнера обновления.
Кроме того, используйте члены контейнера обновления RequestRefresh и RefreshRequested для удобства. refreshContainer.RequestRefresh()
эквивалентноrefreshContainer.Visualizer.RequestRefresh()
, и любой из них вызовет как событие RefreshContainer.RefreshRequested, так и события RefreshVisualizer.RefreshRequested.
Запрос на обновление
Контейнер обновления обрабатывает сенсорные взаимодействия, позволяя пользователю обновить содержимое с помощью сенсорного ввода. Мы рекомендуем реализовывать другие возможности для интерфейсов без сенсорного ввода, например, кнопку "Обновить" или управление голосом.
Чтобы запустить обновление, вызовите метод RequestRefresh.
// See the Examples section for the full code.
private void RefreshButtonClick(object sender, RoutedEventArgs e)
{
RefreshContainer.RequestRefresh();
}
При вызове RequestRefresh визуализатор напрямую переходит из состояния Idle в состояние Refreshing.
Обработка запроса на обновление
Чтобы получить обновленное содержимое, при необходимости, обработайте событие RefreshRequested. В обработчике событий, необходимо добавить код для конкретного приложения, чтобы получить обновленное содержимое.
Аргументы события (RefreshRequestedEventArgs) содержат объект Deferral. Получите дескриптор отсрочки в обработчике событий. Затем отсрочку следует пометить как завершенную, когда код завершил выполнение обновления.
// See the Examples section for the full code.
private async void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)
{
// Respond to a request by performing a refresh and using the deferral object.
using (var RefreshCompletionDeferral = args.GetDeferral())
{
// Do some async operation to refresh the content
await FetchAndInsertItemsAsync(3);
// The 'using' statement ensures the deferral is marked as complete.
// Otherwise, you'd call
// RefreshCompletionDeferral.Complete();
// RefreshCompletionDeferral.Dispose();
}
}
Реагирование на изменения состояния
При необходимости вы можете реагировать на изменения в состоянии визуализатора. Например, для предотвращения отправки нескольких запросов на обновление можно отключить кнопку "Обновить", во время обновления визуализатора.
// See the Examples section for the full code.
private void Visualizer_RefreshStateChanged(RefreshVisualizer sender, RefreshStateChangedEventArgs args)
{
// Respond to visualizer state changes.
// Disable the refresh button if the visualizer is refreshing.
if (args.NewState == RefreshVisualizerState.Refreshing)
{
RefreshButton.IsEnabled = false;
}
else
{
RefreshButton.IsEnabled = true;
}
}
Использование ScrollViewer в RefreshContainer
Примечание.
Содержимое RefreshContainer должно быть прокручиваемым элементом управления, например ScrollViewer, GridView, ListView и т. д. Установка содержимого в элемент управления, например Grid, приведет к неопределенному поведению.
В этом примере показано, как использовать функцию обновления путем оттягивания со средством просмотра прокрутки.
<RefreshContainer>
<ScrollViewer VerticalScrollMode="Enabled"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<!-- Scrollviewer content -->
</ScrollViewer>
</RefreshContainer>
Добавление функции обновления путем оттягивания в ListView
В этом примере показано, как использовать функцию обновления путем оттягивания с представлением списка.
<StackPanel Margin="0,40" Width="280">
<CommandBar OverflowButtonVisibility="Collapsed">
<AppBarButton x:Name="RefreshButton" Click="RefreshButtonClick"
Icon="Refresh" Label="Refresh"/>
<CommandBar.Content>
<TextBlock Text="List of items"
Style="{StaticResource TitleTextBlockStyle}"
Margin="12,8"/>
</CommandBar.Content>
</CommandBar>
<RefreshContainer x:Name="RefreshContainer">
<ListView x:Name="ListView1" Height="400">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ListItemData">
<Grid Height="80">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{x:Bind Path=Header}"
Style="{StaticResource SubtitleTextBlockStyle}"
Grid.Row="0"/>
<TextBlock Text="{x:Bind Path=Date}"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Row="1"/>
<TextBlock Text="{x:Bind Path=Body}"
Style="{StaticResource BodyTextBlockStyle}"
Grid.Row="2"
Margin="0,4,0,0" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RefreshContainer>
</StackPanel>
public sealed partial class MainPage : Page
{
public ObservableCollection<ListItemData> Items { get; set; }
= new ObservableCollection<ListItemData>();
public MainPage()
{
this.InitializeComponent();
Loaded += MainPage_Loaded;
ListView1.ItemsSource = Items;
}
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Loaded -= MainPage_Loaded;
RefreshContainer.RefreshRequested += RefreshContainer_RefreshRequested;
RefreshContainer.Visualizer.RefreshStateChanged += Visualizer_RefreshStateChanged;
// Add some initial content to the list.
await FetchAndInsertItemsAsync(2);
}
private void RefreshButtonClick(object sender, RoutedEventArgs e)
{
RefreshContainer.RequestRefresh();
}
private async void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)
{
// Respond to a request by performing a refresh and using the deferral object.
using (var RefreshCompletionDeferral = args.GetDeferral())
{
// Do some async operation to refresh the content
await FetchAndInsertItemsAsync(3);
// The 'using' statement ensures the deferral is marked as complete.
// Otherwise, you'd call
// RefreshCompletionDeferral.Complete();
// RefreshCompletionDeferral.Dispose();
}
}
private void Visualizer_RefreshStateChanged(RefreshVisualizer sender, RefreshStateChangedEventArgs args)
{
// Respond to visualizer state changes.
// Disable the refresh button if the visualizer is refreshing.
if (args.NewState == RefreshVisualizerState.Refreshing)
{
RefreshButton.IsEnabled = false;
}
else
{
RefreshButton.IsEnabled = true;
}
}
// App specific code to get fresh data.
private async Task FetchAndInsertItemsAsync(int updateCount)
{
for (int i = 0; i < updateCount; ++i)
{
// Simulate delay while we go fetch new items.
await Task.Delay(1000);
Items.Insert(0, GetNextItem());
}
}
private ListItemData GetNextItem()
{
return new ListItemData()
{
Header = "Header " + DateTime.Now.Second.ToString(),
Date = DateTime.Now.ToLongDateString(),
Body = DateTime.Now.ToLongTimeString()
};
}
}
public class ListItemData
{
public string Header { get; set; }
public string Date { get; set; }
public string Body { get; set; }
}
Получение кода примера
- Пример коллекции WinUI. Просмотрите все элементы управления XAML в интерактивном формате.
Связанные статьи
Windows developer