'Xamarin Forms Listview group header not being updated on property changed

I have a Grouped ListView bound to MyGroup (see below) that contains some property but when that property is being changed the view is not getting updated although I call OnPropertyChanged

My Class

     public class MyGroup : ObservableCollection<Items>, INotifyPropertyChanged
     {
         private string foo;
         public string Foo 
         {
             get => foo;
             set 
               {
                  foo = value;
                  OnPropertyChanged(nameof(Foo));
               }
          }
         ...
     }

My View

  <ListView ItemSource="{Binding GroupList}">
     <ListView.GroupHeaderTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid BackgroundColor="#2196F3"
                             Padding="5,5,5,5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Label FontSize="Medium" Text="{Binding Header}" Grid.Column="1" FontAttributes="Italic" TextColor="White"/>
                        <Label Text="{Binding Foo}" TextColor="White" FontSize="Medium" Grid.Column="1" HorizontalOptions="End"/>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.GroupHeaderTemplate>
       </ListView>

MyViewModel

   public List<MyGroup>  GroupList { get => groupList ;set => SetProperty(ref groupList, value); }


Solution 1:[1]

According to your description, you bind Foo in ListView Group header, you said that group header don't update when property changed, but I don't see where do you change this property. I've written a sample - I changed the first item group header when button click.

 public class PersonList1 : ObservableCollection<Person1>, INotifyPropertyChanged
{
    private string _heading;
    public string Heading
    {
        get { return _heading; }
        set
        {
            _heading = value;
            RaisePropertyChanged("Heading");
        }
    }
    public ObservableCollection<Person1> Persons => this;

    
    public event PropertyChangedEventHandler PropertyChanged;       
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
public class Person1
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string DisplayName
    {
        get
        {
            return $"{LastName}, {FirstName}";
        }
    }
}

<StackLayout>
        <ListView IsGroupingEnabled="true" ItemsSource="{Binding ListOfPeople}">
            <ListView.GroupHeaderTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Label Text="{Binding Heading}" />
                    </ViewCell>
                </DataTemplate>
            </ListView.GroupHeaderTemplate>

            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Label Text="{Binding DisplayName}" />
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <Button
            x:Name="btn1"
            Clicked="Btn1_Clicked"
            Text="change header" />
    </StackLayout>

public partial class Page15 : ContentPage
{
    public ObservableCollection<PersonList1> ListOfPeople { get; set; }
   

    public Page15 ()
    {
        InitializeComponent ();

        var sList = new PersonList1()
{
    new Person1() { FirstName = "Sally", LastName = "Sampson" },
    new Person1() { FirstName = "Taylor", LastName = "Swift" },
    new Person1() { FirstName = "John", LastName = "Smith" }
};
        sList.Heading = "S";

        var dList = new PersonList1()
{
    new Person1() { FirstName = "Jane", LastName = "Doe" }
};
        dList.Heading = "D";

        var jList = new PersonList1()
{
    new Person1() { FirstName = "Billy", LastName = "Joel" }
};
        jList.Heading = "J";

        ListOfPeople = new ObservableCollection<PersonList1>()
{
    sList,
    dList,
    jList
};

        this.BindingContext = this;

    }

    private void Btn1_Clicked(object sender, EventArgs e)
    {
        ListOfPeople[0].Heading = "this is test";
    }
}

You can see the the first ListView group header property change as "this is test".

Solution 2:[2]

Your question is not complete enough. Please add detail of how you are calling/setting values to property.

BTW, instead of using this(a wild guess,as you have not provided enough info):

public List<MyGroup>  GroupList { get => groupList ;set => SetProperty(ref groupList, value); }

try this:

public List<MyGroup>  GroupList {
get{
     return groupList;
}
set{
     groupList = value;
     OnPropertyChanged(nameof(GroupList));
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 halfer
Solution 2 bhavya joshi