From what I can gather from the outside there seems to have been a design decision that a ListView would not need to recalculate it's layout after initial creation. This decision has led to a number of forum posting along the lines of "Why don't I see my items in my ListView". Given how varied binding strategies are it is no surprise that this design decision manifests in many ways.
As an interim measure (Hopefully xamarin will revisit this decision) I am using the following subclass in place of the standard ListView. When the collection backing the ItemsSource property has changed, simply update the Version property to force a layout recalculation. I went with a settable property as a trigger so that the viewmodel would not have to have a direct reference to the listview.
This subclass also has a bindable ICommand that will pass the selected item to a viewmodel. Handy for those of us who prefer to keep the display (xaml + code behind) separate from the business logic.
public class ListViewNb : ListView
{
public static BindableProperty ItemClickCommandProperty = BindableProperty.Create<ListViewNb, ICommand>(x => x.ItemClickCommand, null);
public static BindableProperty SourceVersionProperty = BindableProperty.Create<ListViewNb, int>(x => x.SourceVersion,Int32.MinValue);
public ListViewNb()
{
this.ItemTapped += this.OnItemTapped;
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == "SourceVersion")
{
InvalidateMeasure();
}
}
public int SourceVersion
{
get { return (int) GetValue(SourceVersionProperty); }
set { SetValue(SourceVersionProperty,value); }
}
public ICommand ItemClickCommand
{
get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
set { SetValue(ItemClickCommandProperty, value); }
}
private void OnItemTapped(object sender, ItemTappedEventArgs e)
{
if (e.Item == null || this.ItemClickCommand == null || !this.ItemClickCommand.CanExecute(e)) return;
ItemClickCommand.Execute(e.Item);
SelectedItem = null;
}
}