WPFで基本的なフィルター付きリストボックスを実装しようとしています。ユーザーが何かを入力すると、リストは入力されたフレーズで始まる値に絞り込まれます。
私は持っています:
- ビュー:
_
InstitutionFilteringString
データコンテキストとして設定されているViewModelクラスのプロパティにTextプロパティがバインドされているTextBox 、- ItemSourceプロパティがビューモデルの
ICollectionView
名前付きにバインドされているリストボックスInstitutions
- 上記のプロパティを持つ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
は正しく呼び出されます。ここからのアドバイスに従って、セッターはコレクションビューでRefresh()メソッドを呼び出します。FilterInstitutions()
メソッドが呼び出されます。
そして今バグ:文字列が1秒の直前に設定されていても、FilterInstitutions
メソッド内ではnullです。デバッガーを呼び出しスタックの下に移動すると、セッターの観点からは、入力された値に設定されたままですが、フィルタリングメソッド内ではnullになります。
セッターには、コメントアウトされたコード行があります。コメントを外すとバグは修正されますが、どのように行うべきかはほとんどわかりません。
私は何が間違っているのですか?
(わかりませんが、セッターとフィルタリングメソッドがクラスの2つの異なるインスタンスで動作しているように見えます。しかし、どうすれば1つのインスタンスだけを作成し、クラスはクローン化できません)
編集
すみません、嘘をついたようです。コンストラクターにブレークポイントを設定しましたが、実際にクラスの2つのインスタンスを作成し、両方に対してCollectionViewSource.GetDefaultView
同じインスタンスを返すようです。ICollectionView
でも、実際には同じコレクションに対して2つのビューが必要です。まあ、私はこの答えに従いました、そしてそれはうまくいくようです:)