Started to dabble in Xamarin Forms. Two things I cant figure out:
Binding of my Listview:
I have a class with:
public class Mainlist
{
public string Title
{
get;
set;
}
public string Value
{
get;
set;
}
}
My XAML looks like:
<ListView x:Name="mainlist">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<Label Text="{Binding Title}" Font="18"></Label>
<Label Text="{Binding Value}" TextColor="Gray"></Label>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What happens now is that i have a list of URLS. From every URL I am scraping certain info with HTMLAgilityPack foreach loop, which is working fine.
I would like to add the scraped data after each run of the loop to the listview and have it display. Something like "lazy loading".
Up to now i could only figure out how to set the itemsource after all Urls are scraped and have it display at once with something like this:
//set itemsource to URL collection
mainlist.ItemsSource = new List<Mainlist>() {
new Mainlist()
{
//scraped info from each URL
Title = title.ToString().Trim(),
Value = value.ToString().Trim(),
},
};
First, create a view model class, called MyViewModel.cs:
public class MyViewModel : INotifyPropertyChanged
{
// property changed event handler
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<Mainlist> _list;
public ObservableCollection<Mainlist> List
{
get { return _list; }
set
{
_list = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(List)));
}
}
public MyViewModel()
{
_list = new ObservableCollection<Mainlist>();
}
public async void StartScraping()
{
// assuming you are 'awaiting' the results of your scraping method...
foreach (...)
{
await ... scrape a web page ...
var newItem = new Mainlist()
{
Title = title.ToString().Trim(),
Value = value.ToString().Trim()
};
// if you instead have multiple items to add at this point,
// then just create a new List<Mainlist>, add your items to it,
// then add that list to the ObservableCollection List.
Device.BeginInvokeOnMainThread(() =>
{
List.Add(newItem);
});
}
}
}
Now in your page's xaml.cs
code behind file, set the view model as your BindingContext
:
public class MyPage : ContentPage // (assuming the page is called "MyPage" and is of type ContentPage)
{
MyViewModel _viewModel;
public MyPage()
{
InitializeComponent();
_viewModel = new MyViewModel();
BindingContext = _viewModel;
// bind the view model's List property to the list view's ItemsSource:
mainList.setBinding(ListView.ItemsSourceProperty, "List");
}
}
And note that in your view model, you'll need to use an ObservableCollection<T>
instead of a List<T>
, as ObservableCollection<T>
will allow the ListView
to be updated automatically whenever you add or remove items from it.
Also, to ease a bit of confusion, I'd recommend changing the class name from Mainlist
to MainListItem
.