Reputation: 145
Xamarin.Forms 4.0 collection view ItemsSource binding is not working as expected if I set the binding in code behind. The items are displayed based on the initial value of the source collection but, the UI is not updating when the source collection is updated. Same is working if I set the binding in xaml.
public MainPage()
{
this.InitializeComponent();
this.BindingContext = this.mainViewModel = new MainViewModel();
CollectionView courseCollectionView = new CollectionView
{
ItemSizingStrategy = ItemSizingStrategy.MeasureFirstItem,
ItemTemplate = new DataTemplate(typeof(ItemView))
};
courseCollectionView.SetBinding(CollectionView.ItemsSourceProperty,
new Binding() { Source = this.mainViewModel.CountryNames, Mode =
BindingMode.TwoWay });
courseCollectionView.ItemsLayout = new GridItemsLayout(4,
ItemsLayoutOrientation.Vertical);
this.CoursesStack.Children.Clear();
this.CoursesStack.Children.Add(courseCollectionView);
}
View Model Property which is using for ItemsSource Binding:
ObservableCollection<Country> countryNames;
public ObservableCollection<Country> CountryNames
{
get => this.countryNames;
set
{
this.countryNames = value;
RaisePropertyChanged("CountryNames");
}
}
Expected: View should be updated as per the changes made to the ObsevableCollection (add/delete items from collection) which is bound to the ItemsSource Property.
Actual: View is not updated with changes to the ObservableCollection.
Upvotes: 4
Views: 12729
Reputation: 10346
About updating UI when using CollectionView, I do one sample that you can take a look:
public partial class MainPage : ContentPage
{
public mainvidemodel viewmodel { get; set; }
public MainPage()
{
InitializeComponent();
viewmodel = new mainvidemodel();
this.BindingContext = viewmodel;
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "countries");
collectionView.ItemTemplate = new DataTemplate(() =>
{
StackLayout stacklayout = new StackLayout();
Label label1 = new Label();
label1.SetBinding(Label.TextProperty,"Id");
Label label2 = new Label();
label2.SetBinding(Label.TextProperty, "Name");
Label label3 = new Label();
label3.SetBinding(Label.TextProperty, "caption");
stacklayout.Children.Add(label1);
stacklayout.Children.Add(label2);
stacklayout.Children.Add(label3);
return stacklayout;
});
Button btn = new Button() { Text = "btn", WidthRequest = 200, HeightRequest = 50 };
btn.Clicked += Btn_Clicked;
stacklayout1.Children.Add(collectionView);
stacklayout1.Children.Add(btn);
}
private void Btn_Clicked(object sender, EventArgs e)
{
viewmodel.countries.Add(new Country() { Id = 8, Name = "country8", caption = "caption 8" });
}
}
public class mainvidemodel
{
public ObservableCollection<Country> countries { get; set; }
public mainvidemodel()
{
countries = new ObservableCollection<Country>()
{
new Country(){Id=1,Name="country1",caption="caption 1"},
new Country(){Id=2,Name="country2",caption="caption 2"},
new Country(){Id=3,Name="country3",caption="caption 3"},
new Country(){Id=4,Name="country4",caption="caption 4"},
new Country(){Id=5,Name="country5",caption="caption 5"},
new Country(){Id=6,Name="country6",caption="caption 6"},
new Country(){Id=7,Name="country7",caption="caption 7"},
};
}
}
public class Country
{
public int Id { get; set; }
public string Name { get; set; }
public string caption { get; set; }
}
Upvotes: 2
Reputation: 1012
I believe your binding is wrong. Try:
courseCollectionView.SetBinding(CollectionView.ItemsSourceProperty, nameof(mainViewModel.CountryNames));
You need to specify the Path
(mainViewModel.CountryNames
) and not the Source
Upvotes: 2
Reputation: 75
In this case try to extend the MainPage from INotifyPropertyChanged and instead of RaisePropertyChanged("CountryNames") in set property, use OnPropertyChanged()
Upvotes: 0