ObservableCollection<> 未正确加载
ObservableCollection<> not loading properly
我正在尝试对 ObservableCollection<>
进行过滤。我目前的 ObservableCollection<Payee>
作为 ItemsSource
在 GridView
上工作正常。我添加了第二个 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
。
我正在尝试对 ObservableCollection<>
进行过滤。我目前的 ObservableCollection<Payee>
作为 ItemsSource
在 GridView
上工作正常。我添加了第二个 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
。