Reputation: 9632
I have a Xamarin.Forms (3.2, latest version) Picker
implemented as
<Picker x:Name="ClassSelector"
Title="Select Class"
ItemsSource="{Binding Classrooms}"
ItemDisplayBinding="{Binding ClassroomName}"
SelectedItem="{Binding SelectedClassroom}">
</Picker>
The BindingContext is this ViewModel:
public class ClassroomsViewModel : BaseViewModel
{
public ObservableCollection<Classroom> Classrooms { get; set; }
public ClassroomsViewModel()
{
Classrooms = new ObservableCollection<Classroom>(_ClassroomsRepository.GetAll());
}
}
Now, when I add a classroom in the ViewModel
, the Picker dutifully adds the item to its list:
Classrooms.Add(new Classroom() { ClassroomName = "test" }); // this works fine
But if I modify a classroom, the Picker
doesn't update its items list:
Classrooms[0].ClassroomName = "test"; // this doesn't have an effect,
// although the value is set
// in the ObservableCollection
I've also tried explicitly calling:
OnPropertyChanged(); // nothing
OnPropertyChanged("Classrooms"); // nope
If it's important, Classroom
does derive from ObservableObject
:
public class Classroom : ObservableObject
{
private string classroomName;
public string ClassroomName { get => classroomName; set => SetProperty(ref classroomName, value); }
}
Note that I am not replacing the Classrooms
collection with a new ObservableCollection -- as happens in other posts that may appear similar to my issue. I am simply modifying one of the collection's members. When this collection is bound to a different control (like a ListView
), it behaves exactly as expected -- the ListView
updates to reflect the new ClassroomName
.
Can anyone point me to what I'm doing wrong?
Upvotes: 7
Views: 5365
Reputation: 2349
For some reason, setting the source to null and then resetting it works for me:
var items = picker.ItemsSource as List<string>;
items.Add("item");
picker.ItemsSource = null;
picker.ItemsSource = items;
Upvotes: 2
Reputation: 13601
Typically, when we use bindings, we expect the target (a picker-item) to keep itself in sync with the binding source (in this case a Classroom
object) - so, your code, by design, is correct.
However, after digging into Picker
source code in XF github - it looks like it unsubscribes from binding/property-changes after pulling the first value from Binding
. Here you can see the explicit call to UnApply()
to the binding, and subsequently to the binding-expression for picker-item display name.
Invoking OnPropertyChanged("Classrooms");
on CustomerViewModel
(not on Customer
) should technically work. Or, you can try removing the modified Customer
object from the collection, and re-adding at same index to fix this issue. Both of these actions will trigger the ResetItems()
- which in turn should trigger the refresh for picker-item's display name.
Upvotes: 6