I have a binding in XAML which is linked to an list of objects as the ItemsSource. On Android when I update the ItemsSource it updates the binding in the XAML succesfully.
However on iOS this does not work for some reason. Can anyone suggest why ?
Initial declaration of the ItemsSource :
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
CS Code which updates the ItemsSource :
users.ItemsSource = null;
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
This is the Account Group object :
public class Account : INotifyPropertyChanged
{
public string student_unique_id { get; set; }
public string student_fullname { get; set; }
public string organisation_id { get; set; }
public string organisation_title { get; set; }
public string student_token { get;set;}
public string reg_branding_url { get;set;}
public string tint_colour { get;set;}
public string font_colour { get;set;}
public string topup_product_id { get;set;}
public bool isVisible { get; set; }
public string student_initial
{
get
{
return student_fullname[0].ToString();
}
}
public string school_image
{
get
{
return $"{Constants.apiBaseUrl}store/images/uploaded/mobile/{reg_branding_url}";
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class AccountGroup : List<Account>, INotifyPropertyChanged
{
public string organisation_title { get; set; }
public string school_image { get; set; }
public string tint_colour { get; set; }
public string font_colour { get; set; }
public AccountGroup(string orgTitle, string orgImage, string orgTint, string orgFont, List<Account> accounts) : base(accounts)
{
organisation_title = orgTitle;
school_image = orgImage;
tint_colour = orgTint;
font_colour = orgFont;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And this is the XAML with the IsVisible property :
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame IsVisible="{Binding isVisible}" IsEnabled="False" HasShadow="True" BackgroundColor="White" Padding="0">
<Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<behaviors:Expander x:Name="MainExpander" CollapseAnimationLength="500" IsExpanded="False" IsVisible="True" >
Can anyone suggest how to fix this ? Seems strange it works on Android and not iOS. Thanks !
CodePudding user response:
From document From Data Bindings to MVVM,we know that:
ViewModels generally implement the INotifyPropertyChanged interface, which means that the class fires a PropertyChanged event whenever one of its properties changes. The data binding mechanism in Xamarin.Forms attaches a handler to this PropertyChanged event so it can be notified when a property changes and keep the target updated with the new value.
In code Account.cs
, you implemented interface INotifyPropertyChanged
, but you didn't called OnPropertyChanged
.So even the value is changed,the UI will not refresh.
You can refer to the following code:
public class Account: INotifyPropertyChanged
{
string _student_fullname;
public string student_fullname
{
set { SetProperty(ref _student_fullname, value); }
get { return _student_fullname; }
}
private bool _isVisible;
public bool isVisible
{
set { SetProperty(ref _isVisible, value); }
get { return _isVisible; }
}
// you can modify other codes to trigger `SetProperty` just as above code
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Note:
You can modify other fields in class Account
to trigger SetProperty
just as above code. The same with class AccountGroup.cs
In addition,you can define a global variable for your users.ItemsSource
,for example:
public ObservableCollection<AccountGroup> items { get; private set; }
And initialize it as follows:
items = new ObservableCollection<AccountGroup>();
Initial declaration of the ItemsSource :
users.ItemsSource = items;
In this condition,if you want the collectionview to automatically update as items are added, removed and changed in the underlying list, we'll need to use an ObservableCollection
.And we don't need the following code:
users.ItemsSource = null;
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);