Xamarin中的DataBinding和iNotifyPropertyChanged

时间:2015-09-29 13:23:36

标签: c# data-binding xamarin inotifypropertychanged

我目前正在使用Xamarin Forms制作应用。此应用程序将首先调用REST服务以检索数据并显示它们,然后将这些数据存储到SQLite数据库中。我有一个更新按钮,如果我点击它,它将再次提示REST服务以检索更新的数据并在应用程序运行时替换旧数据。我试图实现INotifyPropertyChanged但值不会为我改变。我在下面的代码中遗漏了什么吗?谢谢!

Vitals对象:

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>

2 个答案:

答案 0 :(得分:1)

要让vitals更改Xaml,必须使用新列表替换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的属性,在分配datacontext时我会有

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);
    }
 }

代码审核其他错误

  • OnUpdateasync,这很棒,但它永远不会awaits任何方法调用;因此,所有调用它本质上是同步的,并阻止gui线程等待结果。永远不会阻止gui线程,应用程序似乎会冻结。

答案 1 :(得分:1)

作为选项,您可以使用ObservableCollection而不是List。