Reputation: 738
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.
Upvotes: 4
Views: 9175
Reputation: 2159
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;
}
}
Upvotes: 9