更改源时ListView不会更新 - 即使我实现了PropertyChanged

时间:2016-04-08 12:56:18

标签: c# xaml listview observablecollection propertychanged

我几个小时以来一直在努力解决这个问题:

我正在以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事件吗?

我将非常感谢能够解决这个问题的任何答案或解决方法,或者让我朝着正确的方向前进。

谢谢你,很抱歉很长的帖子。

2 个答案:

答案 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行可能会让您的一天陷入困境。

祝你有个美好的一天,感谢发布以前答案的人: - )