ListViewの項目を並び替える広告
ListViewの項目が自動的に並び替えられるようにするには、ListViewのSortingプロパティをSortOrder.Ascending(昇順)またはSortOrder.Descending(降順)にします。ただしこの方法では、サブアイテムを比較しての並び替えや、数字、時間の並び替えが正しく行われません。 これらの問題を解決するためには、ListViewのListViewItemSorterプロパティに、並べ方を定義したIComparerインターフェイスを実装したクラスのインスタンスを設定します。なお、IComparerによる並び替えについては、「コレクション(または配列)内の要素を方法を指定して並び替える(または検索する)」でも説明しています。 まずはごく簡単な例を示します。ここではListViewコントロール(ListView1)で列ヘッダがクリックされた時に、その列の文字列を昇順に並べ替えるようにします。そのために、まずは次のようなクラスを作成します。 [VB.NET] Imports System.Collections Imports System.Windows.Forms ''' <summary> ''' ListViewの項目の並び替えに使用するクラス ''' </summary> Public Class ListViewItemComparer Implements IComparer Private _column As Integer ''' <summary> ''' ListViewItemComparerクラスのコンストラクタ ''' </summary> ''' <param name="col">並び替える列番号</param> Public Sub New(ByVal col As Integer) _column = col End Sub 'xがyより小さいときはマイナスの数、大きいときはプラスの数、 '同じときは0を返す Public Function Compare(ByVal x As Object, ByVal y As Object) _ As Integer Implements System.Collections.IComparer.Compare 'ListViewItemの取得 Dim itemx As ListViewItem = CType(x, ListViewItem) Dim itemy As ListViewItem = CType(y, ListViewItem) 'xとyを文字列として比較する Return String.Compare(itemx.SubItems(_column).Text, _ itemy.SubItems(_column).Text) End Function End Class [C#] using System.Collections; using System.Windows.Forms; /// <summary> /// ListViewの項目の並び替えに使用するクラス /// </summary> public class ListViewItemComparer : IComparer { private int _column; /// <summary> /// ListViewItemComparerクラスのコンストラクタ /// </summary> /// <param name="col">並び替える列番号</param> public ListViewItemComparer(int col) { _column = col; } //xがyより小さいときはマイナスの数、大きいときはプラスの数、 //同じときは0を返す public int Compare(object x, object y) { //ListViewItemの取得 ListViewItem itemx = (ListViewItem) x; ListViewItem itemy = (ListViewItem) y; //xとyを文字列として比較する return string.Compare(itemx.SubItems[_column].Text, itemy.SubItems[_column].Text); } } このクラスを使って並べ替えを行うには、ListViewのColumnClickイベントハンドラでListViewItemSorterを設定します。次のコードはListViewのあるフォームクラス内に記述してください。これで列ヘッダをクリックすると、並び替えられるようになったはずです。 [VB.NET] 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As EventArgs) Handles MyBase.Load '詳細表示にする ListView1.View = View.Details 'ColumnClickイベントハンドラの追加 AddHandler ListView1.ColumnClick, _ AddressOf ListView1_ColumnClick 'ListViewItemを追加する ListView1.Items.Add( _ New ListViewItem(New String() {"おはよう", "80"})) ListView1.Items.Add( _ New ListViewItem(New String() {"こんにちは", "5"})) ListView1.Items.Add( _ New ListViewItem(New String() {"おやすみ", "100"})) '列の追加 ListView1.Columns.Add("文字列", 100, HorizontalAlignment.Left) ListView1.Columns.Add("数字", 100, HorizontalAlignment.Right) End Sub '列がクリックされた時 Private Sub ListView1_ColumnClick(ByVal sender As Object, _ ByVal e As ColumnClickEventArgs) 'ListViewItemSorterを指定する ListView1.ListViewItemSorter = _ New ListViewItemComparer(e.Column) '並び替える(ListViewItemSorterを設定するとSortが自動的に呼び出される) 'ListView1.Sort() End Sub [C#] //フォームのLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { //詳細表示にする ListView1.View = View.Details; //ColumnClickイベントハンドラの追加 ListView1.ColumnClick += new ColumnClickEventHandler(ListView1_ColumnClick); //ListViewItemを追加する ListView1.Items.Add( new ListViewItem(new string[] {"おはよう", "80"})); ListView1.Items.Add( new ListViewItem(new string[] {"こんにちは", "5"})); ListView1.Items.Add( new ListViewItem(new string[] {"おやすみ", "100"})); //列の追加 ListView1.Columns.Add( "文字列", 100, HorizontalAlignment.Left); ListView1.Columns.Add( "数字", 100, HorizontalAlignment.Right); } //列がクリックされた時 private void ListView1_ColumnClick( object sender, ColumnClickEventArgs e) { //ListViewItemSorterを指定する ListView1.ListViewItemSorter = new ListViewItemComparer(e.Column); //並び替える(ListViewItemSorterを設定するとSortが自動的に呼び出される) //ListView1.Sort(); } さらに拡張せっかくなので、上記のListViewItemComparerクラスをさらに拡張して、より多機能にしてみましょう。 まず、昇順、降順を指定できるようにします。さらに、文字列として並び替えるか、それとも、数字や日時として並び替えるかという「並び替え方」を変更できるようにしましょう。 昇順、降順をいちいち指定するのは面倒なので、並び替える列を指定するColumnプロパティで前と同じ列が指定された時は、トグルで昇順、降順が換わるようにします。また、あらかじめ列ごとに並べ替え方を指定できるようにしておきます。 これらの改良を加えたListViewItemComparerクラスは次のようなものです。 [VB.NET] Imports System Imports System.Collections Imports System.Windows.Forms ''' <summary> ''' ListViewの項目の並び替えに使用するクラス ''' </summary> Public Class ListViewItemComparer Implements IComparer ''' <summary> ''' 比較する方法 ''' </summary> Public Enum ComparerMode [String] [Integer] DateTime End Enum Private _column As Integer Private _order As SortOrder Private _mode As ComparerMode Private _columnModes() As ComparerMode ''' <summary> ''' 並び替えるListView列の番号 ''' </summary> Public Property Column() As Integer Get Return _column End Get Set(ByVal Value As Integer) If _column = value Then If _order = SortOrder.Ascending Then _order = SortOrder.Descending Else If _order = SortOrder.Descending Then _order = SortOrder.Ascending End If End If End If _column = value End Set End Property ''' <summary> ''' 昇順か降順か ''' </summary> Public Property Order() As SortOrder Get Return _order End Get Set(ByVal Value As SortOrder) _order = Value End Set End Property ''' <summary> ''' 並び替えの方法 ''' </summary> Public Property Mode() As ComparerMode Get Return _mode End Get Set(ByVal Value As ComparerMode) _mode = Value End Set End Property ''' <summary> ''' 列ごとの並び替えの方法 ''' </summary> Public WriteOnly Property ColumnModes() As ComparerMode() Set(ByVal Value As ComparerMode()) _columnModes = Value End Set End Property ''' <summary> ''' ListViewItemComparerクラスのコンストラクタ ''' </summary> ''' <param name="col">並び替える列番号</param> ''' <param name="ord">昇順か降順か</param> ''' <param name="mthd">並び替えの方法</param> Public Sub New(ByVal col As Integer, ByVal ord As SortOrder, _ ByVal cmod As ComparerMode) _column = col _order = ord _mode = cmod End Sub Public Sub New() _column = 0 _order = SortOrder.Ascending _mode = ComparerMode.String End Sub 'xがyより小さいときはマイナスの数、大きいときはプラスの数、 '同じときは0を返す Public Function Compare(ByVal x As Object, ByVal y As Object) _ As Integer Implements IComparer.Compare Dim result As Integer = 0 'ListViewItemの取得 Dim itemx As ListViewItem = CType(x, ListViewItem) Dim itemy As ListViewItem = CType(y, ListViewItem) '並べ替えの方法を決定 If Not (_columnModes Is Nothing) And _ _columnModes.Length > _column Then _mode = _columnModes(_column) End If '並び替えの方法別に、xとyを比較する Select Case _mode Case ComparerMode.String result = String.Compare(itemx.SubItems(_column).Text, _ itemy.SubItems(_column).Text) Case ComparerMode.Integer result = Integer.Parse(itemx.SubItems(_column).Text) - _ Integer.Parse(itemy.SubItems(_column).Text) Case ComparerMode.DateTime result = DateTime.Compare( _ DateTime.Parse(itemx.SubItems(_column).Text), _ DateTime.Parse(itemy.SubItems(_column).Text)) End Select '降順の時は結果を+-逆にする If _order = SortOrder.Descending Then result = -result Else If _order = SortOrder.None Then result = 0 End If End If '結果を返す Return result End Function End Class [C#] using System; using System.Collections; using System.Windows.Forms; /// <summary> /// ListViewの項目の並び替えに使用するクラス /// </summary> public class ListViewItemComparer : IComparer { /// <summary> /// 比較する方法 /// </summary> public enum ComparerMode { String, Integer, DateTime }; private int _column; private SortOrder _order; private ComparerMode _mode; private ComparerMode[] _columnModes; /// <summary> /// 並び替えるListView列の番号 /// </summary> public int Column { set { if (_column == value) { if (_order == SortOrder.Ascending) _order = SortOrder.Descending; else if (_order == SortOrder.Descending) _order = SortOrder.Ascending; } _column = value; } get { return _column; } } /// <summary> /// 昇順か降順か /// </summary> public SortOrder Order { set { _order = value; } get { return _order; } } /// <summary> /// 並び替えの方法 /// </summary> public ComparerMode Mode { set { _mode = value; } get { return _mode; } } /// <summary> /// 列ごとの並び替えの方法 /// </summary> public ComparerMode[] ColumnModes { set { _columnModes = value; } } /// <summary> /// ListViewItemComparerクラスのコンストラクタ /// </summary> /// <param name="col">並び替える列番号</param> /// <param name="ord">昇順か降順か</param> /// <param name="mthd">並び替えの方法</param> public ListViewItemComparer( int col, SortOrder ord, ComparerMode cmod) { _column = col; _order = ord; _mode = cmod; } public ListViewItemComparer() { _column = 0; _order = SortOrder.Ascending; _mode = ComparerMode.String; } //xがyより小さいときはマイナスの数、大きいときはプラスの数、 //同じときは0を返す public int Compare(object x, object y) { int result = 0; //ListViewItemの取得 ListViewItem itemx = (ListViewItem) x; ListViewItem itemy = (ListViewItem) y; //並べ替えの方法を決定 if (_columnModes != null && _columnModes.Length > _column) _mode = _columnModes[_column]; //並び替えの方法別に、xとyを比較する switch (_mode) { case ComparerMode.String: result = string.Compare(itemx.SubItems[_column].Text, itemy.SubItems[_column].Text); break; case ComparerMode.Integer: result = int.Parse(itemx.SubItems[_column].Text) - int.Parse(itemy.SubItems[_column].Text); break; case ComparerMode.DateTime: result = DateTime.Compare( DateTime.Parse(itemx.SubItems[_column].Text), DateTime.Parse(itemy.SubItems[_column].Text)); break; } //降順の時は結果を+-逆にする if (_order == SortOrder.Descending) result = -result; else if (_order == SortOrder.None) result = 0; //結果を返す return result; } } このクラスの使用法は例えば次のようになります。 [VB.NET] 'ListViewItemSorterに指定するフィールド Dim listViewItemSorter As ListViewItemComparer 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As EventArgs) Handles MyBase.Load '詳細表示にする ListView1.View = View.Details 'ColumnClickイベントハンドラの追加 AddHandler ListView1.ColumnClick, _ AddressOf ListView1_ColumnClick 'ListViewItemを追加する ListView1.Items.Add( _ New ListViewItem(New String() {"おはよう", "80"})) ListView1.Items.Add( _ New ListViewItem(New String() {"こんにちは", "5"})) ListView1.Items.Add( _ New ListViewItem(New String() {"おやすみ", "100"})) '列の追加 ListView1.Columns.Add("文字列", 100, HorizontalAlignment.Left) ListView1.Columns.Add("数字", 100, HorizontalAlignment.Right) 'ListViewItemComparerの作成と設定 listViewItemSorter = New ListViewItemComparer listViewItemSorter.ColumnModes = _ New ListViewItemComparer.ComparerMode() _ {ListViewItemComparer.ComparerMode.String, _ ListViewItemComparer.ComparerMode.Integer} 'ListViewItemSorterを指定する ListView1.ListViewItemSorter = listViewItemSorter End Sub '列がクリックされた時 Private Sub ListView1_ColumnClick(ByVal sender As Object, _ ByVal e As ColumnClickEventArgs) 'クリックされた列を設定 listViewItemSorter.Column = e.Column '並び替える ListView1.Sort() End Sub [C#] //ListViewItemSorterに指定するフィールド ListViewItemComparer listViewItemSorter; //フォームのLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { //詳細表示にする ListView1.View = View.Details; //ColumnClickイベントハンドラの追加 ListView1.ColumnClick += new ColumnClickEventHandler(ListView1_ColumnClick); //ListViewItemを追加する ListView1.Items.Add( new ListViewItem(new string[] {"おはよう", "80"})); ListView1.Items.Add( new ListViewItem(new string[] {"こんにちは", "5"})); ListView1.Items.Add( new ListViewItem(new string[] {"おやすみ", "100"})); //列の追加 ListView1.Columns.Add("文字列", 100, HorizontalAlignment.Left); ListView1.Columns.Add("数字", 100, HorizontalAlignment.Right); //ListViewItemComparerの作成と設定 listViewItemSorter = new ListViewItemComparer(); listViewItemSorter.ColumnModes = new ListViewItemComparer.ComparerMode[] { ListViewItemComparer.ComparerMode.String, ListViewItemComparer.ComparerMode.Integer }; //ListViewItemSorterを指定する ListView1.ListViewItemSorter = listViewItemSorter; } //列がクリックされた時 private void ListView1_ColumnClick( object sender, ColumnClickEventArgs e) { //クリックされた列を設定 listViewItemSorter.Column = e.Column; //並び替える ListView1.Sort(); }
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。
|
Copyright(C) DOBON!. All rights reserved.
|