我几个小时以来一直在努力解决这个问题:
我正在以MVVM模式构建UWP应用程序。
问题:当我更改ItemSource的属性值时,我无法让ListView的ItemSource更新/重新绑定到ObservableCollection的新实例,即使我已经在属性上实现了IPropertyChanged。 / p>
详细信息: 我正在处理的页面有一个ListView,ItemSource绑定到一个可观察的集合:
页:
<ListView ItemsSource="{Binding Orders}" x:Name="OrderListView"><!--Inner bindings works fine--></ListView>
视图模型:
public ObservableCollection<Order> Orders {
get { return _Orders; }
set { Set(ref _Orders, value); }
}
private ObservableCollection<Order> _Orders;
(...)
//Property changed implementation from video (06:48): https://mva.microsoft.com/en-US/training-courses/windows-10-data-binding-14579?l=O5mda3EsB_1405632527
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//If property is updated with, raise property changed, else don't
public bool Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
return false;
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
按下界面中的按钮时:
<Button Content="Waiter" Click="Waiter_Click" Background="{Binding Waiter, Converter={StaticResource BoolToColorConverter}, FallbackValue='Yellow', TargetNullValue='Red'}"/>
它将在后面的代码中使用“Waiter_Click”事件处理程序:
private void Waiter_Click(object sender, RoutedEventArgs e)
{
var viewModel = ((Button)sender).DataContext as OrderPageViewModel;
if (viewModel.Waiter) viewModel.Waiter = false;
else viewModel.Waiter = true;
}
实现了Waiter属性,因此它在ViewModel中引发了PropertyChangedEvent:
public bool Waiter
{
get { return _waiter; }
set { Set(ref _waiter, value); FilterView(); }
}
private bool _waiter;
按钮在UI中更新 - 这很好。
设置_waiter的私有字段后,我还想过滤掉一些我不想显示的数据。
我在FilterView()中这样做;方法。 这是通过创建一个新的ObservableCollection并设置Orders属性来完成的:
public void FilterView()
{
var filteredOrderList = new ObservableCollection<Order>();
//Sorting is done
Orders = filteredOrderList;
}
现在。我以为代码:Orders = filteredOrderList;将触发Orders属性的“setter”,并像按钮和所有其他工作正常的UI元素一样引发PropertyChanged事件 - 并告诉ListView重新绑定它。然而,似乎ListView正在ObservableCollection的旧实例上运行,并且不关心我的PropertyChanged事件被触发......
我调试了程序,我看到filteredOrderList包含我想要的数据,并且Orders已更改。但它就像ViewList不关心PropertyChanged事件被触发......
我不想在ObservableCollection中添加和删除项目,因为过滤变得非常复杂......我只想用新的替换Orders ObservableCollection,让ViewList反映我的更改...
我错过了什么吗?我不能多次调用PropertyChanged事件吗? (我正在调用它一次用于按钮更新,并且一次调用Orders ObservableCollection)。
为什么ListView没有重新绑定到新列表? - ListView不关心正在触发的PropertyChanged事件吗?
我将非常感谢能够解决这个问题的任何答案或解决方法,或者让我朝着正确的方向前进。
谢谢你,很抱歉很长的帖子。
答案 0 :(得分:1)
答案 1 :(得分:1)
8个半小时后,我发现了我的错误:
我不小心定义了DataContext两次:
<Page.DataContext>
<vm:OrderPageViewModel/>
</Page.DataContext>
并在ListView之前的XAML文件中进一步向下:
<Grid.DataContext>
<vm:OrderPageViewModel/>
</Grid.DataContext>
这导致了我的OrderPageViewModel的两个实例。
然后我的ViewList被绑定到ViewModel的旧实例,并且对ObservableCollection的新ViewModel实例的任何更改都没有反映任何更改。
如果其他人遇到同样的问题:更改ObservableCollection时ViewList不会更新 - 这是因为您创建了ObservableCollection的多个实例。
此外,我发现ObservableCollection仅在添加og时从其中删除对象并使用.Add(),. Remove()和.Clear()方法清除它时更新。如果没有在属性本身中实现它,则调用“CollectionChanged”或“PropertyChanged”是不可能的,就像我在Waiter属性上所做的那样。
我重新设计过滤功能以清除集合并向其添加新元素。它解决了我的问题。 : - )
如果您不小心,XAML中的3行可能会让您的一天陷入困境。祝你有个美好的一天,感谢发布以前答案的人: - )