INotifyPropertyChanged Xamarin字符串值刚刚消失

时间:2016-11-12 02:23:20

标签: xamarin data-binding

我有一个Xamarin.Forms项目,其中ListView填充了一个ObservableCollection。 ObservableCollection中每个项的类(对象)实现INotifyPropertyChanged。 属性在UI中切换正常,但字符串属性消失,永不返回。

我从webservice获取初始值但是只是对值进行了完全静态的更改,以便进行调试,我仍然无法弄明白。

在我的ContentPage类的顶部,我有这个:

public ObservableCollection<GroceryItem> oc;

在我的webservice返回数据之后,我将数据放在ObservableCollection中,并将其作为listview的ItemsSource。像这样:

lvGroceries.ItemsSource = oc;

一切都很好。

XAML

    <ListView x:Name="lvGroceries" ItemTapped="GroceryPdsItemTapped" >               
  <ListView.ItemTemplate > 
    <DataTemplate>
      <ViewCell>              
        <AbsoluteLayout VerticalOptions="Fill">
          <Label Text="{Binding GroceryName}" AbsoluteLayout.LayoutBounds="0,0,200,40" ></Label>
          <Label Text="{Binding strHomeLoc}" AbsoluteLayout.LayoutBounds="200,0,100,40" ></Label>
          <Label Text="{Binding isNeeded}" AbsoluteLayout.LayoutBounds="300,0,50,40" ></Label>                
          <Label Text="someText" BackgroundColor="{Binding myBackgroundColor}" AbsoluteLayout.LayoutBounds="350,0,50,40" ></Label>
        </AbsoluteLayout>        
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

班级 - GroceryItem

public class GroceryItem : INotifyPropertyChanged
{
    public GroceryItem() { }
    public event PropertyChangedEventHandler PropertyChanged;

    private string privateIsNeeded;
    public string isNeeded
    {
        get { return privateIsNeeded; }
        set
        {
            privateIsNeeded = value;
            OnPropertyChanged();
        }
    }

    private Color theColor;
    public Color myBackgroundColor
    {
        get { return theColor; }
        set
        {
            theColor = value;
            OnPropertyChanged();
        }
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

}

点击处理程序。我从ObservableCollection中获取一个项目并更改这两个属性。

    public void GroceryPdsItemTapped(object obj, ItemTappedEventArgs e)
{
    if (e.Item == null)
    {
        return;
    }
    var g = ((GroceryItem)e.Item);
    foreach (var gr in oc)
    {
        if (gr.GroceryId == "27769")
        {   // the UI changes because the myBackgroundColor property in the GroceryItem class is watching for a value change
            gr.myBackgroundColor = (gr.myBackgroundColor == Color.Yellow) ? Color.Blue : Color.Yellow;
            gr.isNeeded = (gr.isNeeded == "true" || gr.isNeeded == "blah" || gr.isNeeded == "false") ? "notblah" : "blah";
        }
    }
}

“颜色”在UI中切换正常,但isNeeded字符串值在第一次点击时消失,从不重新显示

想法?

1 个答案:

答案 0 :(得分:0)

这里有几个问题。首先,您需要在ObservableCollection运行OnPropertyChanged()时进行更改,如下所示:

private ObservableCollection<GroceryItem> _oc;

public ObservableCollection<GroceryItem> oc {
    get { return _oc ?? (_oc = new ObservableCollection<GroceryItem>()); }
    set {
        if(_oc != value) {
            _oc = value;
            OnPropertyChanged();
        }
    }
}

现在你应该在ViewModel中拥有所有这些,但是既然你没有,你需要在代码隐藏中将ContentPage设置为BindingContext,如下所示:

public partial class MyGroceryPage : ContentPage {

    public MyGroceryPage() { BindingContext = this; }
}

您还需要将ObservableCollection绑定到ListView.ItemSource而不是分配它。看起来像这样:

<ListView ItemSource="{Binding oc}"/>

如果您执行上述操作然后进入代码并执行lvGroceries.ItemsSource = oc;,则会覆盖您在XAML中执行的绑定,因此执行此操作。相反,当您从Web服务获取数据时,您只需将其分配给现有的ObservableCollection

public async Task GetGroceryData() {
    List<GroceryItem> myData = await GroceryService.GetGroceriesAsync();

    oc = new ObservableCollection<GroceryItem>(myData);
}

首先尝试所有这些,如果您的商品仍未更新,您可能需要尝试从ObservableCollection中删除它们,更改属性,然后将其添加回来:

public void GroceryPdsItemTapped(object obj, ItemTappedEventArgs e) {

    if (e.Item == null) { return; }

    var g = ((GroceryItem)e.Item);

    foreach (var gr in oc.ToList()) {

        if (gr.GroceryId == "27769") {   // the UI changes because the myBackgroundColor property in the GroceryItem class is watching for a value change
            oc.Remove(gr);
            gr.myBackgroundColor = (gr.myBackgroundColor == Color.Yellow) ? Color.Blue : Color.Yellow;
            gr.isNeeded = (gr.isNeeded == "true" || gr.isNeeded == "blah" || gr.isNeeded == "false") ? "notblah" : "blah";
            oc.Add(gr);
        }
    }
}