Xamarin iOS - XAML IsVisible 绑定在 ItemsSource 更改时不更新
Xamarin iOS - XAML IsVisible binding does not update when ItemsSource is changed
我在 XAML 中有一个绑定,它作为 ItemsSource 链接到一个对象列表。在 Android 上,当我更新 ItemsSource 时,它会成功更新 XAML 中的绑定。
但是在 iOS 上,由于某些原因这不起作用。谁能告诉我为什么?
ItemsSource 的初始声明:
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
更新 ItemsSource 的 CS 代码:
users.ItemsSource = null;
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
这是帐户组对象:
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));
}
}
这是带有 IsVisible 属性 的 XAML :
<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" >
谁能建议如何解决这个问题?它适用于 Android 而不是 iOS 似乎很奇怪。谢谢!
从文献From Data Bindings to MVVM,我们知道:
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.
在代码Account.cs
中,你实现了接口INotifyPropertyChanged
,但你没有调用OnPropertyChanged
。所以即使值改变了,UI也不会刷新.
您可以参考以下代码:
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;
}
注:
您可以修改class中的其他字段Account
来触发SetProperty
,就像上面的代码一样。与 class AccountGroup.cs
相同
另外,你可以为你的users.ItemsSource
定义一个全局变量,例如:
public ObservableCollection<AccountGroup> items { get; private set; }
并初始化如下:
items = new ObservableCollection<AccountGroup>();
ItemsSource 的初始声明:
users.ItemsSource = items;
在这种情况下,如果您希望 collectionview 在基础列表中添加、删除和更改项目时自动更新,我们需要使用 ObservableCollection
。我们不需要以下代码:
users.ItemsSource = null;
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
我在 XAML 中有一个绑定,它作为 ItemsSource 链接到一个对象列表。在 Android 上,当我更新 ItemsSource 时,它会成功更新 XAML 中的绑定。
但是在 iOS 上,由于某些原因这不起作用。谁能告诉我为什么?
ItemsSource 的初始声明:
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
更新 ItemsSource 的 CS 代码:
users.ItemsSource = null;
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);
这是帐户组对象:
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));
}
}
这是带有 IsVisible 属性 的 XAML :
<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" >
谁能建议如何解决这个问题?它适用于 Android 而不是 iOS 似乎很奇怪。谢谢!
从文献From Data Bindings to MVVM,我们知道:
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.
在代码Account.cs
中,你实现了接口INotifyPropertyChanged
,但你没有调用OnPropertyChanged
。所以即使值改变了,UI也不会刷新.
您可以参考以下代码:
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;
}
注:
您可以修改class中的其他字段Account
来触发SetProperty
,就像上面的代码一样。与 class AccountGroup.cs
另外,你可以为你的users.ItemsSource
定义一个全局变量,例如:
public ObservableCollection<AccountGroup> items { get; private set; }
并初始化如下:
items = new ObservableCollection<AccountGroup>();
ItemsSource 的初始声明:
users.ItemsSource = items;
在这种情况下,如果您希望 collectionview 在基础列表中添加、删除和更改项目时自动更新,我们需要使用 ObservableCollection
。我们不需要以下代码:
users.ItemsSource = null;
users.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<AccountGroup>(Accounts);