参考
WPF/XAML : DataGrid の表示内容を TextBox への入力内容でフィルタリングする - i++
上記サイトにお世話になりました。
ポイントは以下3つとのこと。
- DataGrid の ItemsSource に CollectionViewSource.View を使う
- CollectionViewSource.Filter にフィルタリング用の関数を登録する
- TextBox の入力に変更がある度に CollectionViewSource.View.Refresh() を呼ぶ
サンプル
Model
名前と年齢の情報を持つPersonクラス
internal class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } }
ViewModel
コンストラクタでFilterにフィルタリング用の関数を登録しています。
internal class MainWindowViewModel : INotifyPropertyChanged { private string _quickFilter = ""; private ObservableCollection<Person> _people = new ObservableCollection<Person>(); private CollectionViewSource _peopleSource; public string QuickFilter { get => _quickFilter; set => this.SetQuickFilter(value); } public ObservableCollection<Person> People { get => _people; set => SetProperty(ref _people, value); } public CollectionViewSource PeopleSource { get => _peopleSource; set => SetProperty(ref _peopleSource, value); } public MainWindowViewModel() { this._people.Add(new Person($"田中0", 20)); this._people.Add(new Person($"伊藤0", 21)); this._people.Add(new Person($"佐藤0", 22)); this._people.Add(new Person($"鈴木0", 27)); this._people.Add(new Person($"田中1", 30)); this._people.Add(new Person($"鈴木1", 43)); this._people.Add(new Person($"田中2", 32)); this._people.Add(new Person($"田中3", 38)); _peopleSource = new CollectionViewSource(); _peopleSource.Filter += PeopleSource_Filter; _peopleSource.Source = _people; } private void PeopleSource_Filter(object sender, FilterEventArgs e) { if (e.Item != null) { // テキストが空の時はフィルタリングなし if (String.IsNullOrEmpty(this.QuickFilter)) { e.Accepted = true; } else { // 部分一致を受け入れる Person p = e.Item as Person; e.Accepted = p.Name.Contains(this.QuickFilter); } } } private void SetQuickFilter(string value) { if (this._quickFilter == value) return; this._quickFilter = value; OnPropertyChanged(nameof(this.QuickFilter)); // filtering this.PeopleSource.View.Refresh(); } #region INotifyPropertyChanged Support public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null) { if (Equals(field, value)) { return false; } field = value; this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); return true; } #endregion INotifyPropertyChanged Support }
XAML
メインウィンドウの中身を以下のように実装。
<Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBox Text="{Binding Path=QuickFilter}"/> <DataGrid Grid.Row="1" ItemsSource="{Binding Path=PeopleSource.View}" /> </Grid>