我有一个Xamarin.Forms项目,其中ListView填充了一个ObservableCollection。 ObservableCollection中每个项的类(对象)实现INotifyPropertyChanged。
我从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字符串值在第一次点击时消失,从不重新显示
想法?
答案 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);
}
}
}