【问题标题】:DataBinding and iNotifyPropertyChanged in XamarinXamarin 中的 DataBinding 和 iNotifyPropertyChanged
【发布时间】:2015-12-27 00:06:51
【问题描述】:

我目前正在使用 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));
        }
    }
}

生命体征视图

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>

【问题讨论】:

  • 您在 Update 方法的哪个位置修改 ViewModel?您能告诉我们您是如何设置数据绑定的吗?
  • 感谢您回复@Jason!我刚刚添加了数据绑定部分。另外,我应该如何修改 ViewModel?
  • 您的绑定看起来正确。但是当你获得新数据时你需要更新你的 ViewModel——它不会自动发生。大概您会将 vitals 属性设置为新的数据集合。
  • 你有如何做到这一点的任何代码示例吗?我认为它不仅仅是:新的 VitalsViewModel (patUpdate);
  • 您的 ViewModel 具有公共生命体征属性 - 只需将其设置为您从更新中获得的新数据集。

标签: c# data-binding xamarin inotifypropertychanged


【解决方案1】:

作为一个选项,您可以使用 ObservableCollection 代替 List。

【讨论】:

  • 我也在尝试这样做,同时应用 Fody.PropertyChange 轻推。
【解决方案2】:

要使 vitals 在 Xaml 中发生更改,必须将 List&lt;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);
    }
 }

代码审查其他错误

  • OnUpdateasync,这很好,但它从来没有 awaits 任何方法调用;因此,对它的所有调用本质上都是同步的,并阻塞了等待结果的 gui 线程。永远不要阻止 gui 线程,应用程序会显示为冻结。

【讨论】:

  • 感谢您回复@OmegaMan! 1. 那只是应该被注释掉的旧代码。我重新编辑了第一页。 2. 谢谢指出!当我尝试更新时,我确实注意到应用程序冻结;将来可能会对此有所作为。
猜你喜欢
  • 1970-01-01
  • 2015-04-07
  • 2017-08-13
  • 2020-02-25
  • 2016-09-24
  • 2020-07-28
  • 1970-01-01
  • 2014-12-04
  • 1970-01-01
相关资源
最近更新 更多