ObservableCollection<> 未正确加载

ObservableCollection<> not loading properly

我正在尝试对 ObservableCollection<> 进行过滤。我目前的 ObservableCollection<Payee> 作为 ItemsSourceGridView 上工作正常。我添加了第二个 ObservableCollection<Payee>,称为 FilteredPayees,用作 ItemsSource。出于某种原因,当我尝试过滤项目时,GridView 显示为空白。

这是我使用的代码:

private void FilterPayees()
{
    if (!_settings.ShowInactivePayees)
    {
        var filtered = _payees.Where(p => p.IsOpen == true);
        _filteredPayees = new ObservableCollection<Payee>(filtered);
    }
    else
    {
        _filteredPayees = _payees;
    }
    this.FilteredPayees = _filteredPayees;
}

基本上,如果 ShowInactivePayees 设置关闭,它应该过滤掉不活跃的收款人。如果打开,则只需使用完整的 _payees 集合。奇怪的是,如果我将最后一行更改为:

this.FilteredPayees = _payees;

然后 GridView 将显示所有收款人,就像 "show inactive payees" 设置打开时一样。我设置了断点,_filteredPayees 集合中有 35 个项目(如果不过滤则为 65 个)。它似乎不是任何类型的 "object not set to an instance of an object" 或类似的东西。有什么原因吗

this.FilteredPayees = _payees;

可以,但是

_filteredPayees = _payees;
this.FilteredPayees = _filteredPayees;

不会?

编辑

我现在可以通过摆脱 FilteredPayees 属性 来让它工作。我只是在 OnNavigatedTo() 事件处理程序中过滤原始 Payees 集合,这与我调用 FilteredPayees().

的位置完全相同
// load payees
var payees = await _payeesRepository.LoadAllAsync();

if (!_settings.ShowInactivePayees)
{
    payees = payees.Where(p => p.IsOpen);
}
payees = payees.OrderBy(p => p.CompanyName);

this.Payees = new ObservableCollection<Payee>(payees);

我添加的唯一部分是 if (!_settings.ShowInactivePayees) ... 块。我使用 FilteredPayees 属性 的原因是我可以在 Payees 属性 中加载完整的集合,如果 ShowInactivePayees 设置则不需要重新加载已更改 - 只需更改集合的过滤器。

要在 WPF 中过滤集合,使用 ICollectionView 可能更容易。例如:

public class Foo
{
    private List<Payee> _payees;

    private ICollectionView _filteredPayees;

    public ICollectionView FilteredPayees
    {
        get { return _filteredPayees; }
    }

    public Foo()
    {
        _payees = GetPayees();
        _filteredPayees = CollectionViewSource.GetDefaultView(_payees);
        _filteredPayees.Filter = FilterPayees;
    }

    private bool FilterPayees(object item)
    {
        var payee = item as Payee;

        if (payee == null)
        {
            return false;
        }

        if (_settings.ShowInactivePayees)
        {
            return true;
        }

        return payee.IsOpen;
    }
}

您可以像绑定其他 属性 一样绑定 属性 FilteredPayees。优点是,你不需要两个属性,你可以避免你想绑定哪个集合的逻辑。

_filteredPayees = new ObservableCollection<Payee>(filtered);

这里你创建了一个全新的对象,这不是 ObservableCollection 可以自动观察到的东西。可能的解决方案是在此行之后再次在您的 GridView 上设置 ItemsSource。

您正在将新对象分配给 FilteredPayees 属性,因此必须通知 GridView 属性 FilteredPayees 已更改。 FilteredPayees的setter里应该有RaisePropertyChanged("FilteredPayees")或者你的通知码。

另外,GridView.ItemsSource的绑定模式不应该是BindingMode.OneTime