XAMLを使わないWPF入門26「ListView + ソート機能」

コンピュータ

リストビューのヘッダークリックでソートするコードになります。
この記事のソート機能はListViewとデータソースとなるコレクションとデータバインドが前提となります。

実行時スクリーンショット
image
ヘッダークリック後のスクリーンショット
image

ファイル名:NoXAML26ListViewSort.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:App.cs


using System;
using System.Windows;

namespace NoXAML26ListViewSort;

public class App : Application
{
    [STAThread]
    public static void Main(string[] args)
    {
        var app = new App();
        app.Run();
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        var win = new MainWindow();
        win.Show();
    }
}

ファイル名:AssemblyInfo.cs


using System.Windows;

[assembly:ThemeInfo(
    ResourceDictionaryLocation.None,            //where theme specific resource dictionaries are located
                                                //(used if a resource is not found in the page,
                                                // or application resource dictionaries)
    ResourceDictionaryLocation.SourceAssembly   //where the generic resource dictionary is located
                                                //(used if a resource is not found in the page,
                                                // app, or any theme specific resource dictionaries)
)]

ファイル名:MainWindow.cs


using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace NoXAML26ListViewSort;

public class ItemData
{
    public string Name { get; set; } = "";
}

public class MainWindow : Window
{
    private ListView _listView;
    private GridViewColumnHeader? _lastHeaderClicked;
    private ListSortDirection _lastDirection = ListSortDirection.Ascending;

    public MainWindow()
    {
        Title = "NoXAML ListView ソート";
        Width = 350;
        Height = 250;

        // データ
        var items = new List<ItemData>
        {
            new ItemData { Name = "りんご" },
            new ItemData { Name = "ばなな" },
            new ItemData { Name = "みかん" },
        };

        _listView = new ListView
        {
            ItemsSource = items
        };

        var gridView = new GridView();
        _listView.View = gridView;

        // Name列(ヘッダークリックでソート)
        var nameHeader = new GridViewColumnHeader { Content = "Name" };
        nameHeader.Click += GridViewColumnHeader_Click;
        var nameColumn = new GridViewColumn
        {
            Header = nameHeader,
            DisplayMemberBinding = new Binding("Name"),
            Width = 220
        };
        gridView.Columns.Add(nameColumn);

        this.Content = _listView;
    }

    // ヘッダークリックでソート
    void GridViewColumnHeader_Click(object sender, RoutedEventArgs e)
    {
        var headerClicked = e.OriginalSource as GridViewColumnHeader;
        if (headerClicked == null || headerClicked.Role == GridViewColumnHeaderRole.Padding) return;

        var binding = headerClicked.Column?.DisplayMemberBinding as Binding;
        var sortBy = binding?.Path?.Path ?? "Name";

        var direction = (headerClicked == _lastHeaderClicked && _lastDirection == ListSortDirection.Ascending)
            ? ListSortDirection.Descending : ListSortDirection.Ascending;

        Sort(sortBy, direction);

        _lastHeaderClicked = headerClicked;
        _lastDirection = direction;
    }

    void Sort(string sortBy, ListSortDirection direction)
    {
        ICollectionView dataView = CollectionViewSource.GetDefaultView(_listView.ItemsSource);
        dataView.SortDescriptions.Clear();
        dataView.SortDescriptions.Add(new SortDescription(sortBy, direction));
        dataView.Refresh();
    }
}

コメント