INotifyPropertyChanged Xamarin字符串值刚刚消失 [英] INotifyPropertyChanged Xamarin string value just disappears

查看:64
本文介绍了INotifyPropertyChanged Xamarin字符串值刚刚消失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Xamarin.Forms项目,其中的ListView装有ObservableCollection。 ObservableCollection中每个项目的类(对象)实现INotifyPropertyChanged。 Color属性可以在用户界面中很好地切换,但是字符串属性会消失并且永远不会返回。

I have a Xamarin.Forms project with a ListView populated with an ObservableCollection. The class (object) that is each item in the ObservableCollection implements INotifyPropertyChanged. A Color property toggles fine in the UI but a string property disappears and never returns.

我从Web服务获取了初始值,但是只是对它进行了完全静态的更改值,用于调试,但仍然无法弄清。

I get the initial values from a webservice but then just do a completely static change of the values, for debugging and I still can't figure it out.

在ContentPage类的顶部,我有以下内容:

At the top of the my ContentPage class I have this:

public ObservableCollection<GroceryItem> oc;

在Web服务返回数据后,我将数据放入ObservableCollection中,并使其成为ItemsSource用于列表视图。像这样:

After my webservice has returned with the data I put the data in the ObservableCollection and make that, the ItemsSource for the listview. Like this:

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

The class - 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中获取一个项目并更改了两个属性。

The click handler. I grab an item from the ObservableCollection and change the two properties.

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

颜色在用户界面,但isNeeded字符串值在第一次点击时就消失了,再也不会出现

The Color toggles fine in the UI but the isNeeded string value disappears on the first tap and never re-appears

想法?

推荐答案

此处有几个问题。首先,您需要在更改后,使 ObservableCollection 运行 OnPropertyChanged()

A couple issues here. First is that you need to make your ObservableCollection run OnPropertyChanged() when it has been changed like so:

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 -像这样:

Now you should really have all of this in a ViewModel but since you do not, you need to set your ContentPage as the BindingContext from within your code-behind like this:

public partial class MyGroceryPage : ContentPage {

    public MyGroceryPage() { BindingContext = this; }
}

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

You also need to be binding your ObservableCollection to your ListView.ItemSource instead of assigning it. That looks like this:

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

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

If you do the above and then you go into your code behind and execute lvGroceries.ItemsSource = oc; then that would overwrite the binding that you did in your XAML, so do not do that. Instead, when you get data from your web service, you would just assign it to your existing ObservableCollection:

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

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

请先尝试所有操作,如果您的商品仍未更新,则可能需要尝试从 ObservableCollection 中删除​​它们,更改属性,然后将它们重新添加到以下内容中:

Try all of that first and if your items are still not updating you might want to try removing them from your ObservableCollection, changing the properties, then adding them back in:

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

这篇关于INotifyPropertyChanged Xamarin字符串值刚刚消失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆