Reputation: 23
I have a page that looks like this. I tested out the code using a List but I need to use an ObservableCollection as the contents of the data will change after it's initially populated. My problem is that when I change from a List to ObservableCollection I no longer see any data appearing.
public YourPage()
{
var viewModel = _vm = new YourPageViewModel()
var dataTemplate = new DataTemplate(()=>
{
var mygrid = new MyGrid ();
mygrid.SetBinding(MyGrid.TextProperty, "Text");
return mygrid;
});
StackLayout stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, _vm.ListOfText);
BindableLayout.SetItemTemplate(stackLayout, dataTemplate);
Content = stackLayout;
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.OnAppearing();
}
And a ViewModel
public partial class YourPageViewModel : BaseViewModel
{
private ObservableCollection<TestModel> _listOfText;
public ObservableCollection<TestModel> ListOfText{
get => _listOfText;
set => SetProperty(ref _listOfText, value);
}
public void OnAppearing()
{
var tempList = ...;
ListOfText = new ObservableCollection<TestModel>(tempList);
}
}
Given this situation with an ObservableCollection then the data template doesn't seem to show any data.
Does anyone have an idea what might be wrong?
Upvotes: 0
Views: 158
Reputation: 23
The solutions given work for when the data is populate one time after the binding is set up but then after that the layout will not be refreshed.
To solve this problem what is needed is to place the DataTemplate in a CollectionView
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "ListOfText");
collectionView.ItemTemplate = new DataTemplate(() =>
{
var mygrid = new MyGrid ();
mygrid.SetBinding(MyGrid.TextProperty, "Text");
return mygrid;
});
Content = collectionView;
When this is done the ObservableCollection can be refreshed at any time and the screen layout will change when it's refreshed.
Upvotes: 0
Reputation: 15001
Becasue when you set the data-binding in the constructor of your page,the ListOfText
is not populated the data until you call _vm.OnAppearing();
in OnAppearing()
method.
You could try to pipulate the data in the constructor of your viewmodel:
public partial class YourPageViewModel : BaseViewModel
{
private ObservableCollection<TestModel> _listOfText;
public ObservableCollection<TestModel> ListOfText{
get => _listOfText;
set => SetProperty(ref _listOfText, value);
}
public YourPageViewModel ()
{
var tempList = ...;
_listOfText = new ObservableCollection<TestModel>(tempList);
}
}
and then you don't need to call _vm.OnAppearing();
in OnAppearing()
method.
You need to make sure that you have populated your data when you bind it.
Upvotes: 1
Reputation: 34063
You will want to create the ObservableCollection
only once. If you use data-binding on it, it will subscribe to certain events that will emit the changes in the collection.
By doing ListOfText = new ObservableCollection<TestModel>(tempList);
it will cause those events to be disconnected and your data won't show up. Instead, change it to be more like this
public partial class YourPageViewModel : BaseViewModel
{
// This changed
private ObservableCollection<TestModel> _listOfText = new ObservableCollection<TestModel>(tempList);
public ObservableCollection<TestModel> ListOfText{
get => _listOfText;
set => SetProperty(ref _listOfText, value);
}
public void OnAppearing()
{
var tempList = ...;
// This changed
ListOfText.Clear();
foreach (var text in tempList)
ListOfText.Add(text);
}
}
Notice how I only create the ObservableCollection
once and repopulate each time instead of creating a new one.
Upvotes: 1