ObservableCollection<>;加载不正确

本文关键字:加载 不正确 gt lt ObservableCollection | 更新日期: 2023-09-27 18:03:34

我正在尝试在ObservableCollection<>上实现过滤。我当前的ObservableCollection<Payee>可以像GridView上的ItemsSource一样正常工作。我添加了第二个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将显示所有收款人,就像打开"显示非活动收款人"设置时一样。我设置了断点,_filteredPayees集合中有35个项目(不过滤时为65个(。它似乎不是任何类型的"未设置为对象实例的对象"或类似的东西。

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设置发生更改,则不需要重新加载-只需更改集合的筛选器即可。

ObservableCollection<>;加载不正确

您正在为FilteredPayees属性分配一个新对象,因此必须通知GridView属性FilteredPayees已更改。FilteredPayees的设置器中应该有RaisePropertyChanged("FilteredPayees")或您的通知代码。

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

对于在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。