WPFのListViewでヘッダークリックでソート

C# コンピュータ
C#

ソースコード

<Window x:Class="ListViewSort01.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:ListViewSort01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListView ItemsSource="{Binding Files}">
            <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>
    </Grid>
</Window>
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.Collections.ObjectModel;
using System.Windows.Automation.Peers;
using System.Diagnostics;

using System.ComponentModel;

namespace ListViewSort01;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public class FilesItem
    {
        public string Name { get; set; } = "";
        public int Length { get; set; } = 0;
    }
    public ObservableCollection<FilesItem> Files { get; set; } = [];
    public MainWindow()
    {
        InitializeComponent();

        Files.Add(new FilesItem(){Name = "abc.txt", Length = 600 });
        Files.Add(new FilesItem(){Name = "def.txt", Length = 300 });
        Files.Add(new FilesItem(){Name = "ghi.txt", Length =  50 });

        HeadName1.Click += (s, e) =>
        {
            //Debug.Print("HeadName1 Click");
            const string propertyName = "Name";
            var collectionView = CollectionViewSource.GetDefaultView(Files);
            if (collectionView.SortDescriptions.Any() == false || collectionView.SortDescriptions[0].PropertyName != propertyName)
            {
                collectionView.SortDescriptions.Clear();
                collectionView.SortDescriptions.Add(new SortDescription(propertyName, ListSortDirection.Descending));
                return;
            }
            var d = collectionView.SortDescriptions[0].Direction == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;
            collectionView.SortDescriptions.Clear();
            collectionView.SortDescriptions.Add(new SortDescription(propertyName, d));            
        };

        DataContext = this;
    }
}

実行

ヘッダーの「名前」をクリックすると

ソートされます。

説明

ソートの部分のみをコードビハインドで書き直したら、ソースコードが短くなって理解しやすくなるのではと期待しましたが、それほど短くはなりませんでした。XAMLのネストの深さは辟易します。

ソートのコード部分をみると、

データソースのFilesからcollectionViewを生成し、

var collectionView = CollectionViewSource.GetDefaultView(Files);

既存のソートの条件?をクリアし、

collectionView.SortDescriptions.Clear();

そのオブジェクトにソートのキーとなる項目を追加

collectionView.SortDescriptions.Add(new SortDescription(propertyName, ListSortDirection.Descending));

すると、バインド先のListViewが並べ替えられるように見受けられます。

コメント