前回の記事 では、カスタムデータを利用して DataGridView を表示する方法をまとめましたが、 今回はその続きで DataGridView で カスタムデータ を ソート可能にする 方法 を見ていきます。
目次
概要
DataGridView で ソート可能 にすることは簡単で、
以下に載せる SortableBindingList
を DataGridView.DataSource へ設定するだけです。
なんのひねりもないのでサクッとサンプルコードを見ていきましょう。
ソート可能なバインディングリスト
何と言ってもこのソースコードが必要! これさえあればカスタムデータも DataGridView でソートできる! そんな魔法のようなリストオブジェクトのサンプルコードを以下に載せます。
SortableBindingList.cs
namespace Sample { using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; /// <summary> /// ソート可能なバインディングリストクラス /// </summary> /// <typeparam name="T">リスト内容</typeparam> public class SortableBindingList<T> : BindingList<T> where T : class { /// <summary> /// ソート済みかどうか /// </summary> private bool isSorted; /// <summary> /// 並べ替え操作の方向 /// </summary> private ListSortDirection sortDirection = ListSortDirection.Ascending; /// <summary> /// ソートを行う抽象化プロパティ /// </summary> private PropertyDescriptor sortProperty; /// <summary> /// SortableBindingList クラス の 新しいインスタンス を初期化します。 /// </summary> public SortableBindingList() { } /// <summary> /// 指定した リストクラス を利用して SortableBindingList クラス の 新しいインスタンス を初期化します。 /// </summary> /// <param name="list">SortableBindingList に格納される System.Collection.Generic.IList</param> public SortableBindingList(IList<T> list) : base(list) { } /// <summary> /// リストがソートをサポートしているかどうかを示す値を取得します。 /// </summary> protected override bool SupportsSortingCore { get { return true; } } /// <summary> /// リストがソートされたかどうかを示す値を取得します。 /// </summary> protected override bool IsSortedCore { get { return this.isSorted; } } /// <summary> /// ソートされたリストの並べ替え操作の方向を取得します。 /// </summary> protected override ListSortDirection SortDirectionCore { get { return this.sortDirection; } } /// <summary> /// ソートに利用する抽象化プロパティを取得します。 /// </summary> protected override PropertyDescriptor SortPropertyCore { get { return this.sortProperty; } } /// <summary> /// ApplySortCore で適用されたソートに関する情報を削除します。 /// </summary> protected override void RemoveSortCore() { this.sortDirection = ListSortDirection.Ascending; this.sortProperty = null; this.isSorted = false; } /// <summary> /// 指定されたプロパティおよび方向でソートを行います。 /// </summary> /// <param name="prop">抽象化プロパティ</param> /// <param name="direction">並べ替え操作の方向</param> protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) { // ソートに使う情報を記録 this.sortProperty = prop; this.sortDirection = direction; // ソートを行うリストを取得 var list = Items as List<T>; if (list == null) { return; } // ソート処理 list.Sort(this.Compare); // ソート完了を記録 this.isSorted = true; // ListChanged イベントを発生させます this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); } /// <summary> /// 比較処理を行います。 /// </summary> /// <param name="lhs">左側の値</param> /// <param name="rhs">右側の値</param> /// <returns>比較結果</returns> private int Compare(T lhs, T rhs) { // 比較を行う var result = this.OnComparison(lhs, rhs); // 昇順の場合 そのまま、降順の場合 反転させる return (this.sortDirection == ListSortDirection.Ascending) ? result : -result; } /// <summary> /// 昇順として比較処理を行います。 /// </summary> /// <param name="lhs">左側の値</param> /// <param name="rhs">右側の値</param> /// <returns>比較結果</returns> private int OnComparison(T lhs, T rhs) { object lhsValue = (lhs == null) ? null : this.sortProperty.GetValue(lhs); object rhsValue = (rhs == null) ? null : this.sortProperty.GetValue(rhs); if (lhsValue == null) { return (rhsValue == null) ? 0 : -1; } if (rhsValue == null) { return 1; } if (lhsValue is IComparable) { return ((IComparable)lhsValue).CompareTo(rhsValue); } if (lhsValue.Equals(rhsValue)) { return 0; } return lhsValue.ToString().CompareTo(rhsValue.ToString()); } } }
実装サンプル
フォームには dataGridView1
という DataGridView が配置されている前提で SortableBindingList
の使用例を以下に載せます。
Form1.cs
public partial class Form1 : Form { public Form1() { this.InitializeComponent(); var list = new SortableBindingList<UserModel>() { new UserModel() { Id = "0010", FirstName = "Kurihara", LastName = "Yuki", Email = "yuki.kurihara@gmail.com", Password = "*****" }, new UserModel() { Id = "0020", FirstName = "Momotsuki", LastName = "Shinya", Email = "shinya.momotsuki@gmail.com", Password = "*****" } }; this.dataGridView1.DataSource = list; } }
ソートできない状態にする場合は BindingSource
を挟んで DataGridView.DataSource へリストを設定していましたが、
SortableBindingList
を利用する場合はそのまま DataGridView.DataSource へリストを設定できます。
これを実行すると、以下のようにカラムタイトルを選択してソートできるようになり、ソート方向を示す三角アイコンが表示されるようになります。
参考記事
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!