Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populate ListView when page is loaded (Xamarin.Forms) using a Command

I have tried unsuccessfully to populate a ListView bound to an ObservableCollection when a page is loaded. Currently I have it working with a button (bound to a Command) with the following code.

View:

<Button Text="Load Items" Command="{Binding LoadItemsCommand}"></Button>
<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" />
<ScrollView>
  <ListView ItemsSource="{Binding Items}">      
    .....
  </ListView>
</ScrollView>

View.cs:

private ItemsViewModel _itemsViewModel;

public ItemsView()
{
    InitializeComponent();
    _itemsViewModel = new ItemsViewModel();
    BindingContext = _itemsViewModel;
}

ViewModel:

public ObservableCollection<Item> Items{ get; set; }
public Command LoadItemsCommand { get; set; }

public ItemsViewModel()
{
    Items = new ObservableCollection<Item>();
    _isBusy = false;

    LoadItemsCommand = new Command(async () => await LoadItems(), () => !IsBusy);    
}

public async Task LoadItems()
{
    if (!IsBusy)
    {
        IsBusy = true;
        await Task.Delay(3000); 
        var loadedItems = ItemsService.LoadItemsDirectory(); 

        foreach (var item in loadedItems)
            Items.Add(item);

        IsBusy = false;
    }
}

This works perfectly with the button but I have no idea how to do it automatically. I tried binding the RefreshCommand property of the listview to my command but nothing.

like image 934
Esteban Verbel Avatar asked Oct 24 '25 16:10

Esteban Verbel


1 Answers

There are a couple of ways, but the best one would be to kick off a task in your view models constructor that loads the data. I would also not add each item to the observable collection as this would mean a UI update on end add. It would be better to replace the collection completely once all data is loaded.

Something like:

public ItemsViewModel()
{
    Items = new ObservableCollection<Item>();
    _isBusy = false;

    Task.Run(async () => await LoadItems());    
}

public async Task LoadItems()
{
    var items = new ObservableCollection<Item>(); // new collection

    if (!IsBusy)
    {
        IsBusy = true;
        await Task.Delay(3000); 
        var loadedItems = ItemsService.LoadItemsDirectory(); 

        foreach (var item in loadedItems)
            items.Add(item);                // items are added to the new collection    

        Items = items;   // swap the collection for the new one
        RaisePropertyChanged(nameof(Items)); // raise a property change in whatever way is right for your VM

        IsBusy = false;
    }
}
like image 136
JimBobBennett Avatar answered Oct 26 '25 05:10

JimBobBennett



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!