DataBinding and iNotifyPropertyChanged in Xamarin
本文关键字:Xamarin in iNotifyPropertyChanged and DataBinding | 更新日期: 2023-09-27 18:14:57
我目前正在使用Xamarin Forms制作应用程序。这个应用程序将首先调用一个REST服务来检索数据并显示它们,然后将这些数据存储到SQLite数据库中。我有一个更新按钮,如果我点击它,它会提示REST服务再次检索新数据并替换旧数据,而应用程序正在运行。我试图实现INotifyPropertyChanged,但值只是不会为我改变。我错过了什么与我的代码下面?谢谢!
命脉对象:
public class Vitals
{
public string Height { get; set; }
public string ID { get; set; }
public string Weight { get; set; }
}
更新方法:
async void OnUpdate(object sender, EventArgs e)
{
string tempUser = globalPatient.Username;
string tempPin = globalPatient.PIN;
patUpdate = patientManager.GetPatientByUsername (tempUser, tempPin).Result;
App.PatientDB.DeletePatient(tempID);
App.PatientDB.AddNewPatient (patUpdate, tempPin);
DisplayAlert ("Updated", "Your information has been updated!", "OK");
}
VitalsViewModal:
public class VitalsViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public VitalsViewModel (Patient patient)
{
vitals = patient.Vitals;
}
private List<Vitals> _vitals;
public List<Vitals> vitals {
get {return _vitals; }
set {
if (_vitals != value) {
_vitals = value;
OnPropertyChanged ("vitals");
}
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
VitalsView
public partial class VitalsView : ContentPage, INotifyPropertyChanged
{
PatientManager patientManager = new PatientManager ();
Patient globalPatient;
public event PropertyChangedEventHandler PropertyChanged;
public VitalsView (Patient patientZero)
{
InitializeComponent ();
BindingContext = new VitalsViewModel (patientZero);
}
}
Xaml
<ListView x:Name="Vitals" ItemsSource="{Binding vitals}" RowHeight="80" BackgroundColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Vertical" Spacing="0" Padding="15">
<Grid>
<Label Font="17" Text="{Binding Height} " FontAttributes="Bold" TextColor="#449BC4" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" />
<Label Font="14" Text="{Binding Weight, StringFormat='Weight: {0}'}" FontAttributes="Bold" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" />
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
</Grid>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
要在Xaml中更改vitals
,必须用新列表替换List<vitals
的整个列表。
即使病人改变了,它的生命体征从更新中是新的,你已经绑定了一个孤儿patient.vitals
,其patient
引用仍然有效。因此没有更改。
需要将vitals
的引用从旧的更改为新的。
我的建议是:
async void OnUpdate(object sender, EventArgs e)
{
string tempUser = globalPatient.Username;
string tempPin = globalPatient.PIN;
patUpdate = patientManager.GetPatientByUsername (tempUser, tempPin).Result;
App.PatientDB.DeletePatient(tempID);
App.PatientDB.AddNewPatient (patUpdate, tempPin);
MyCurrenViewModel.vitals = patUpdate.Vitals; // Replace old vitals
DisplayAlert ("Updated", "Your information has been updated!", "OK");
}
在上面的例子中,我将在页面上创建一个名为MyCurrentViewModel
的属性,当分配数据上下文时,我将使用
public partial class VitalsView : ContentPage, INotifyPropertyChanged
{
VitalsViewModel MyCurrentViewModel { get; set; }
PatientManager patientManager = new PatientManager ();
PatientDemo globalPatient;
public event PropertyChangedEventHandler PropertyChanged;
public VitalsView (Patient patientZero)
{
InitializeComponent ();
//BindingContext = new VitalsViewModel (patientZero);
BindingContext = MyCurrentViewModel = new VitalsViewModel (patientZero);
}
}
代码复查其他错误
-
OnUpdate
是async
,这很好,但它从来没有awaits
任何方法调用;因此,对它的所有调用本质上是同步的,并阻塞GUI线程等待结果。永远不要阻塞gui线程,否则应用程序会被冻结。
作为一个选项,你可以使用ObservableCollection来代替List。