ListViewで文字フィルターをするビヘイビア版です。
ソートのビヘイビアが出来たので、フィルターもビヘイビア化出来るだろうと試みました。


WPFのListViewでヘッダークリックでソート2 - ListViewSortBehavior
ListViewのヘッダークリックでソートするコードを確認しました。再利用する場合、コードビハインドだと中身を理解するのが大変なので、ListViewSortBehaviorを作ることで再利用しやすくしてみました。前回の記事ソースコードファ...
ただ、フィルターの場合フィルター用の文字を入力するテキストボックスが必要で、それとリストビューをどのようにして連携してビヘイビアに落とし込むかが課題になります。
ソースコード
ファイル名:FileInfoModel.cs
public class FileInfoModel
{
public string Name { get; set; } = "";
public int Length { get; set; } = 0;
}
ファイル名:ListViewFilterBehavior.cs
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Microsoft.Xaml.Behaviors;
namespace ListViewSort03;
public class ListViewFilterBehavior : Behavior<ListView>
{
public TextBox FilterTextBox
{
get { return (TextBox)GetValue(FilterTextBoxProperty); }
set { SetValue(FilterTextBoxProperty, value); }
}
public static readonly DependencyProperty FilterTextBoxProperty =
DependencyProperty.Register("FilterTextBox", typeof(TextBox), typeof(ListViewFilterBehavior));
private ICollectionView? _collectionView;
protected override void OnAttached()
{
base.OnAttached();
_collectionView = CollectionViewSource.GetDefaultView(AssociatedObject.ItemsSource);
if (FilterTextBox != null)
{
FilterTextBox.TextChanged += FilterTextBox_TextChanged;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (FilterTextBox != null)
{
FilterTextBox.TextChanged -= FilterTextBox_TextChanged;
}
}
private void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (_collectionView != null)
{
_collectionView.Filter = o =>
{
if (string.IsNullOrEmpty(FilterTextBox.Text))
{
return true;
}
else
{
// フィルタリングのロジックをここに記述します。
if (o is FileInfoModel item)
{
return item.Name.Contains(FilterTextBox.Text, StringComparison.OrdinalIgnoreCase);
}
else
{
return false;
}
}
};
}
}
}
ファイル名:MainWindow.xaml
<Window
x:Class="ListViewSort03.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ListViewSort03"
mc:Ignorable="d"
Title="ListViewSort03"
Height="450" Width="800"
xmlns:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<StackPanel>
<TextBox x:Name="filterTextBox"/>
<ListView ItemsSource="{Binding Files}">
<i:Interaction.Behaviors>
<local:ListViewFilterBehavior FilterTextBox="{Binding ElementName=filterTextBox}" />
</i:Interaction.Behaviors>
<ListView.View>
<GridView>
<GridViewColumn Width="200">
<GridViewColumnHeader
x:Name="HeadName1"
Content="名前" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Width="100"
TextAlignment="Left"
Text="{Binding Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="200">
<GridViewColumnHeader
x:Name="HeadLength1"
Content="長さ" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Width="100"
TextAlignment="Right"
Text="{Binding Length}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Grid>
</Window>
ファイル名:MainWindowViewModel.cs
using System.Diagnostics;
using System.ComponentModel;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System.Reactive.Disposables;
namespace ListViewSort03;
public class MainWindowViewModel : INotifyPropertyChanged
{
// INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
/**************************************************************************
* プロパティ
**************************************************************************/
// ファイルの一覧
public ReactiveCollection<FileInfoModel> Files { get; private set; } = [];
public MainWindowViewModel()
{
PropertyChanged += (s, e) => {};
Files.AddOnScheduler(new FileInfoModel(){Name = "a.txt", Length = 99});
Files.AddOnScheduler(new FileInfoModel(){Name = "b.txt", Length = 88});
Files.AddOnScheduler(new FileInfoModel(){Name = "c.txt", Length = 77});
}
}
実行
テキストボックスに「a」と入力するとリストビューがフィルタリングされます。
説明
リストビューフィルターのビヘイビアをテキストボックスにバインドしています。
なるべくViewとビヘイビアで完結するようにしていますが、FileInfoModelを使っているので再利用の場合セットで考える必要があります。
コメント