Trabalhar com listas no Xamarin Forms nem sempre é uma tarefa simples. Precisamos pensar na exibição de dados, consumos de internet e e tudo mais. Neste post vamos ver uma estratégia para atualizar o conteúdo da ListView sob demanda, conforme o usuário estiver vendo, o Infinite Scroll, utilizando o Prism, sem necessidade de plugin, sem necessidade de criar um novo Custom Control o Custom Renderer. Criando o evento na ListView Se você não conhece o Prism, eu já falei dele anteriormente neste post. Vou partir do princípio que você já possui o Prism instalado no projeto. O primeiro passo é construir a lista no XAML: <ListView HasUnevenRows="true" ItemsSource="{Binding Produtos}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Label Text="{Binding Nome}"> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> Adicionando o Prism EventToCommandBehaviors Até aqui não há nada de novo do que já estamos acostumados a fazer com ListViews no Xamarin. Para conseguir fazer o infinite scroll de modo desacoplado e testável, a grande sacada do Prism é permitir que nós consigamos usar os eventos na View Model e não no code behind. Para isto, o primeiro passo é adicionar o namespace dos Behaviors do Prism na sua Página: xmlns:behaviors="clr-namespace:Prism.Behaviors;assembly=Prism.Forms" Depois de adicionar os Behaviors do Prism, podemos utilizar o EventToCommandBehavior. A classe EventToCommandBehavior fornece uma maneira conveniente de, em XAML, “ligar” eventos ao ICommand da View Model utilizando o padrão MVVM para evitar o que seja necessário escrever códigos no Code Behind. <ListView.Behaviors> <behaviors:EventToCommandBehavior Command="{Binding ItemAppearingCommand}"; EventArgsParameterPath="Item" EventName="ItemAppearing"/> </ListView.Behaviors> No código acima nós adicionamos a propriedade Behaviors da ListView, nativo do Xamarin, e dentro dela, adicionamos os Behaviors do Prism. Dos Behaviors do Prism selecionamos o EventToCommandBehavior, quer fará toda a mágica acontecer. Ele precisa de ao menos 3 parâmetros para ser executado: Command (que será o Command executado na View Model quando o evento acontecer), EventArgsParameterPath (que será os argumentos enviados ao Command) e EventName (que é o nome do evento que queremos escutar). Em EventArgsParameterPath estamos passando o texto Item. Isto é suficiente para o Prism entender que estamos querendo obter o item atual que está sendo exibido neste momento na tela. Ele se encarregará de obte-lo da tela e envia-lo para o Command. Veja como ficou a página inteira após adicionar os códigos acima: <ContentPage x:Class=&quot;MeuApp.Views.ProdutosPage> xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:behaviors="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"> <ContentPage.Content> <StackLayout> <ListView HasUnevenRows="true" ItemsSource="{Binding Produtos}"> <ListView.Behaviors> <behaviors:EventToCommandBehavior Command="{Binding ItemAppearingCommand}" EventArgsParameterPath="Item" EventName="ItemAppearing" /> </ListView.Behaviors> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Label Text="{Binding Nome}"/> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> </ContentPage> Obtendo o último elemento da lista e adicionando mais items Pronto, agora tudo o que precisamos fazer é adicionar um Command na nossa ViewModel que receba o item como parâmetro e adicione mais items a lista Produtos: public ICommand ItemAppearingCommand { get; set; } E então instancia-lo no construtor da ViewModel: ItemAppearingCommand = new Command((item) => { if(Produtos.Last().Id == ((Produto)item).Id) { AtualizarListaDeProdutos(); } }); No Command acima estamos verificando se o último item da nossa lista de Produtos é o mesmo item que foi enviado pelo EventToCommandBehavior da view para view model. Perceba que pedimos o parâmetro item na instanciação do Command. Ele receberá o valor do Item que pedimos na View na propriedade EventArgsParameterPath. Veja a classe completa: using MvvmHelpers; using Prism.Mvvm; using Prism.Navigation; using Prism.Services; using MeuApp.Models; using MeuApp.Services; using System.Windows.Input; using Xamarin.Forms; namespace MeuApp.ViewModels { public class ProdutosPageViewModel : BindableBase, INavigatingAware { public readonly IProdutoService _produtoService; public ObservableRangeCollection<Produto> Produtos { get; set; } public ICommand ItemAppearingCommand { get; set; } public ProdutosPageViewModel(IProdutoService produtoService) { _produtoService = produtoService; Produtos = new ObservableRangeCollection<Produto>(); ItemAppearingCommand = new Command((item) => { if(Produtos[Produtos.Count -1].Id == ((Produto)item).Id) { AtualizarListaDeProdutos(); } }); } public void OnNavigatedFrom(INavigationParameters parameters) { } public void OnNavigatingTo(INavigationParameters parameters) { AtualizarListaDeProdutos(); } private void AtualizarListaDeProdutos() => Produtos.AddRange(_produtoService.ObterProdutos()); } } Feedback para o usuário Pronto! Se você quiser, pode também adicionar um loading no rodapé da ListView para indicar ao usuário que está buscando mais items: <ListView.Footer> <StackLayout IsVisible="{Binding BuscandoMaisProdutos}" Margin="0, 10, 0, 10"> <ActivityIndicator IsRunning="true" WidthRequest="40" HeightRequest="40"/> </StackLayout> </ListView.Footer> E então setar a flag BuscandoMaisProdutos como true antes de chamarmos o serviço que irá buscar os produtos e como false quando os produtos retornarem: if(Produtos[Produtos.Count -1].ProdutoId == ((Produto)item).ProdutoId) { Device.BeginInvokeOnMainThread(()=> BuscandoMaisProdutos = true); AtualizarListaDeProdutos(); Device.BeginInvokeOnMainThread(() => BuscandoMaisProdutos = false); } Estamos utilizando o Device.BeginInvokeOnMainThread para garantir que a atualização da propriedade e a notificação da alteração ocorreram na Main Thread e a view será notificada desta atualização. Conclusão O EventToCommandBehavior pode ser usado para tratar diversos eventos na View Model, isto facilita bastante a testabilidade do sistema, além de reduzir a complexidade. Você pode ler mais sobre o EventToCommandBehavior aqui. Imagem utilizada no post PixaBay Compartilhe isso:Clique para compartilhar no Twitter(abre em nova janela)Clique para compartilhar no Facebook(abre em nova janela)Curtir isso:Curtir Carregando...