I got a List in the ViewModel and the UI is not reacting to changes of property values. It is about the button (SfChip) background colour, which is not updated. (a selected button is red, all others are white).
Here is the XAML:
<syncfusion:SfChipGroup ItemsSource="{Binding PageButtonList}" >
<syncfusion:SfChipGroup.ItemTemplate>
<DataTemplate x:DataType="models:PageModel">
<syncfusion:SfChip Text="{Binding Title}"
Background="{Binding IsCurrentPage, Converter={StaticResource BoolToColorConverter}}"
TextColor="Black" />
</DataTemplate>
</syncfusion:SfChipGroup.ItemTemplate>
</syncfusion:SfChipGroup>
The Background color is bound to a bool
using a BoolToColorConverter
:
<toolkit:BoolToObjectConverter x:Key="BoolToColorConverter"
TrueObject="{x:Static Colors.Red}"
FalseObject="{x:Static Colors.White}"/>
The boolean value of IsCurrentPage
is initially true, so the colour is red. Every time I add a PageModel element to the PageButtonList, I set all IsCurrentPage
properties to false
, only the last one is true
.
private void UpdatePageButtonList()
{
foreach (var pageModel in PageButtonList)
{
pageModel.IsCurrentPage = pageModel.Id == CurrentPageNumber;
}
}
Even if list entries are gradually added and more SfChip's are displayed, they all remain on red. I can set a breakpoint in the method UpdatePageButtonList()
and see that IsCurrentPage
is set to false
for the first list entries.
Probably the UI does not recognise the change of the property or the converter does not work.
Why does the SfChip's background colour not turn white?
public class PageModel
{
public int Id { get; set; }
public string Title => (Id + 1).ToString();
public bool IsCurrentPage { get; set; }
public PageModel(int id)
{
Id = id;
IsCurrentPage = true;
}
}
The problem is that your IsCurrentPage
property doesn't invoke a PropertyChanged
event and thus the UI doesn't get notified about the change.
In MAUI, all properties that can change their values and are used in binding expressions that need to update the UI when the value is updated, need to be observable. This applies to ViewModels and Models alike.
When you use a Model class in your ViewModel, e.g. in a List<PageModel>
or ObservableCollection<PageModel>
and you bind to a property of said PageModel
, e.g. IsCurrentPage
, then this property must be observable.
Make sure that your PageModel
class implements the INotifyPropertyChanged interface, either by doing so manually or by using the Source Generators from the MVVM Community Toolkit:
public class PageModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public int Id { get; set; }
public string Title => (Id + 1).ToString();
private bool _isCurrentPage;
public bool IsCurrentPage
{
get => _isCurrentPage;
set
{
if(value == _isCurrentPage) return;
_isCurrentPage = value;
OnPropertyChanged();
}
}
public PageModel(int id)
{
Id = id;
IsCurrentPage = true;
}
}
public partial class PageModel : ObservableObject
{
public int Id { get; set; }
public string Title => (Id + 1).ToString();
[ObservableProperty]
private bool _isCurrentPage; //becomes IsCurrentPage public property
public PageModel(int id)
{
Id = id;
IsCurrentPage = true;
}
}