我正在尝试在 WPF 中实现一个基本的过滤列表框。用户键入一些内容,列表缩小到以键入的短语开头的值。
我有:
- 一个视图:
- 一个 TextBox,其 Text 属性绑定到
InstitutionFilteringString
ViewModel 类中的属性,该属性设置为数据上下文, - 一个 ListBox,其 ItemSource 属性绑定到视图模型中的一个
ICollectionView
命名Institutions
- 一个 TextBox,其 Text 属性绑定到
- 具有上述属性的ViewModel类。
代码(去掉了不相关的部分):
class ChooseInstitiutionAndPublisherPageViewModel : WizardPageViewModelBase
{
private ICollectionView _institutions;
public ICollectionView Institutions
{
get
{
return _institutions;
}
set
{
_institutions = value;
NotifyPropertyChanged("Institutions");
}
}
private string _institutionFilteringString;
public string InstitutionFilteringString
{
get
{
return _institutionFilteringString;
}
set
{
_institutionFilteringString = value;
NotifyPropertyChanged("InstitutionFilteringString");
//WORKAROUND
//Institutions.Filter = new Predicate<object>(FilterInstitutions);
Institutions.Refresh();
}
}
public ChooseInstitiutionAndPublisherPageViewModel(WizardViewModel parent)
: base(parent)
{
Institutions = CollectionViewSource.GetDefaultView(CentralRepository.Instance.GetInstitutions());
Institutions.Filter = new Predicate<object>(FilterInstitutions);
}
private bool FilterInstitutions(object obj)
{
//I may refer directly to the field or through the property, it doesn't change anything
if (_institutionFilteringString == null || _institutionFilteringString.Length == 0)
return true;
//some more filtering, irrelevant
//[cut]
}
}
视图和绑定:
<TextBox Text="{Binding Path=InstitutionFilteringString, Mode=TwoWay}" Height="23" Margin="6,6,87,0" Name="institutionNameTextBox" VerticalAlignment="Top" TextChanged="institutionNameTextBox_TextChanged" />
<ListBox Margin="6,35" Name="institutionsListBox" ItemsSource="{Binding Path=Institutions}" IsSynchronizedWithCurrentItem="True" />
所以,说到点子上了。的设置器InstitutionFilteringString
被正确调用。根据此处的建议,setter 调用集合视图上的 Refresh() 方法。该FilterInstitutions()
方法被调用。
现在是错误:即使字符串是在一秒钟之前设置的,但在FilterInstitutions
方法内部它是空的。如果我在调用堆栈中使用调试器,从设置器的角度来看,它仍然设置为类型化的值,但在过滤方法内部它是空的。
在 setter 中有一行注释掉的代码。取消注释它可以修复错误,但这几乎不是应该如何完成的。
我究竟做错了什么?
(我不确定,但在我看来,setter 和过滤方法似乎对类的两个不同实例进行操作。但怎么可能,我只创建一个实例,并且类不可克隆)
编辑
对不起,我好像撒谎了。我在构造函数中放置了一个断点,看来我确实创建了该类的两个实例并为两者CollectionViewSource.GetDefaultView
返回相同的实例。ICollectionView
好吧,但我实际上希望对同一个集合有两个视图。好吧,我已经遵循了这个答案,它似乎有效:)