Xamarin.Forms 在 CollectionView 中实现延迟加载
Xamarin.Forms implement Lazy Loading in CollectionView
这是我的 CollectionView xaml 文件:
<ContentPage.Content>
<Grid>
<StackLayout>
<RefreshView IsRefreshing="{Binding IsRefreshing, Mode=OneWay}"
Command="{Binding LoadRefreshCommand}">
<CollectionView ItemsSource="{Binding Photos}" SelectedItem="{Binding SelectedPhoto}" RemainingItemsThreshold="10" RemainingItemsThresholdReachedCommand="{Binding LoadNewPhotosCommand}" >
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="#3498DB">
<Grid RowSpacing="0" ColumnSpacing="0" Padding="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference CurrentPage}, Path=BindingContext.LoadPhotosCommand}" />
</Grid.GestureRecognizers>
<Image Aspect="AspectFit" HeightRequest="50" Source="{Binding Url}" Grid.Column="0"></Image>
<Frame HasShadow="False" VerticalOptions="Center" Grid.Column="1">
<Label Text="{Binding Title}"></Label>
</Frame>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</StackLayout>
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
<Frame IsVisible="{Binding IsBusy}" BorderColor="#3498DB" HasShadow="False" BackgroundColor="#eeeeee">
<StackLayout>
<ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" HorizontalOptions="Center" VerticalOptions="Center"></ActivityIndicator>
<Label TextColor="#3498DB" Text="Loading Data, Please Wait..." HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HorizontalOptions="Center" VerticalOptions="Center" IsVisible="{Binding IsBusy}"/>
</StackLayout>
</Frame>
</StackLayout>
</Grid>
</ContentPage.Content>
这是 ViewModel 中的构造函数:
public MainPageViewModel()
{
LoadPhotosCommand = new Command(execute: async () => await ExecuteGetAllPhotos());
LoadRefreshCommand = new Command(execute: async () => await ExecuteRefreshGetAllPhotos());
LoadRefreshCommand = new Command(execute: async () => await ExecuteGetNewPhotos());
Photos = new ObservableCollection<Photo>();
PhotosModel = new PhotosModel();
SelectedPhoto = new Photo();
}
这是我如何获取数据的 ViewModel 中的代码:
async Task ExecuteGetAllPhotos()
{
if (IsBusy)
return;
try
{
IsBusy = true;
Photos.Clear();
PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
if(PhotosModel!=null)
{
foreach (var photo in PhotosModel.Photos)
{
Photos.Add(photo);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
当读取 100,200,500 条数据时,此代码工作正常 entries.But 当我读取 5000 条数据条目时,应用程序冻结并想要强制停止。它等待大约 2-3 分钟来显示数据。所以我想为延迟加载或无限滚动实现一些逻辑。
这是RemainingItemsThresholdReachedCommand
的命令函数,应该为滚动数据编写逻辑:
async Task ExecuteGetNewPhotos()
{
if (IsBusy)
return;
try
{
//some logic here---------->
IsBusy = true;
Photos.Clear();
PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
if (PhotosModel != null)
{
foreach (var photo in PhotosModel.Photos)
{
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
我不明白延迟加载或滚动是如何工作的。有人可以帮忙吗?
当您的页面加载时,您应该调用您的服务来加载前 X 行数据。假设 X=50
- 它可以是您想要的任何值。
当用户滚动到列表底部时,CollectionView
将触发 RemainingItemsThresholdReachedCommand
。触发时,您应该从您的服务中获取下一个 X 数量的项目并将它们添加到您的 ItemsSource
.
为此,您的服务需要能够增量加载数据。
这是我的 CollectionView xaml 文件:
<ContentPage.Content>
<Grid>
<StackLayout>
<RefreshView IsRefreshing="{Binding IsRefreshing, Mode=OneWay}"
Command="{Binding LoadRefreshCommand}">
<CollectionView ItemsSource="{Binding Photos}" SelectedItem="{Binding SelectedPhoto}" RemainingItemsThreshold="10" RemainingItemsThresholdReachedCommand="{Binding LoadNewPhotosCommand}" >
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="#3498DB">
<Grid RowSpacing="0" ColumnSpacing="0" Padding="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference CurrentPage}, Path=BindingContext.LoadPhotosCommand}" />
</Grid.GestureRecognizers>
<Image Aspect="AspectFit" HeightRequest="50" Source="{Binding Url}" Grid.Column="0"></Image>
<Frame HasShadow="False" VerticalOptions="Center" Grid.Column="1">
<Label Text="{Binding Title}"></Label>
</Frame>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</StackLayout>
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
<Frame IsVisible="{Binding IsBusy}" BorderColor="#3498DB" HasShadow="False" BackgroundColor="#eeeeee">
<StackLayout>
<ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" HorizontalOptions="Center" VerticalOptions="Center"></ActivityIndicator>
<Label TextColor="#3498DB" Text="Loading Data, Please Wait..." HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HorizontalOptions="Center" VerticalOptions="Center" IsVisible="{Binding IsBusy}"/>
</StackLayout>
</Frame>
</StackLayout>
</Grid>
</ContentPage.Content>
这是 ViewModel 中的构造函数:
public MainPageViewModel()
{
LoadPhotosCommand = new Command(execute: async () => await ExecuteGetAllPhotos());
LoadRefreshCommand = new Command(execute: async () => await ExecuteRefreshGetAllPhotos());
LoadRefreshCommand = new Command(execute: async () => await ExecuteGetNewPhotos());
Photos = new ObservableCollection<Photo>();
PhotosModel = new PhotosModel();
SelectedPhoto = new Photo();
}
这是我如何获取数据的 ViewModel 中的代码:
async Task ExecuteGetAllPhotos()
{
if (IsBusy)
return;
try
{
IsBusy = true;
Photos.Clear();
PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
if(PhotosModel!=null)
{
foreach (var photo in PhotosModel.Photos)
{
Photos.Add(photo);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
当读取 100,200,500 条数据时,此代码工作正常 entries.But 当我读取 5000 条数据条目时,应用程序冻结并想要强制停止。它等待大约 2-3 分钟来显示数据。所以我想为延迟加载或无限滚动实现一些逻辑。
这是RemainingItemsThresholdReachedCommand
的命令函数,应该为滚动数据编写逻辑:
async Task ExecuteGetNewPhotos()
{
if (IsBusy)
return;
try
{
//some logic here---------->
IsBusy = true;
Photos.Clear();
PhotosModel = await InstagramCloneDataStore.GetAllPhotos();
if (PhotosModel != null)
{
foreach (var photo in PhotosModel.Photos)
{
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
var msg = ex.Message;
}
finally
{
IsBusy = false;
}
}
我不明白延迟加载或滚动是如何工作的。有人可以帮忙吗?
当您的页面加载时,您应该调用您的服务来加载前 X 行数据。假设 X=50
- 它可以是您想要的任何值。
当用户滚动到列表底部时,CollectionView
将触发 RemainingItemsThresholdReachedCommand
。触发时,您应该从您的服务中获取下一个 X 数量的项目并将它们添加到您的 ItemsSource
.
为此,您的服务需要能够增量加载数据。