方法 : ListView のアイテムを並べ替える

更新 : 2007 年 11 月

.NET Compact Framework では、ListViewSort メソッドがサポートされていませんが、ArrayListIComparer インターフェイスおよび Sort メソッドを使用してアイテムを並べ替えることができます。

次の表は、3 つのクラスの定義を示しています。

クラス

説明

ColHeader

このクラスは、ColumnHeader クラスから派生したものであり、ListView コントロールに列を追加するため、およびクリックされた列を並べ替えるために使用します。このクラスには、並べ替えの方向を指定するための ascending プロパティがあります。true の場合は昇順、false の場合は降順になります。

SortWrapper

いずれかの列をクリックすると、ListItem ごとにこのクラスのインスタンスが作成され、ArrayList に追加されます。ラップされている各アイテムには、クリックした列のインデックスを格納したプロパティが含まれています。

このクラスには SortComparer クラスが含まれています。

SortComparer

このクラスでは、SortWrapper クラス内に、IComparer インターフェイスが実装してあります。このインターフェイスの Compare メソッドでは、ArrayList を並べ替えるときに、2 つのオブジェクトを同時に比較します。

ColumnClick イベントのイベント ハンドラでは、並べ替え操作を次のように実行します。

  1. クリックされた列を判断するために、ColHeader クラスのインスタンスを作成します。

  2. 逆方向で並べ替えるために、ColHeader オブジェクトの ascending プロパティを設定します。

  3. リスト内の項目数を取得します。

  4. BeginUpdate メソッドを使用して、画面描画を無効にします。

  5. ListView アイテムの SortWrapper を ArrayList に追加します。

  6. ArrayList 内の要素を、SortComparer クラスを使用して並べ替えます。このクラスに実装されている IComparer インターフェイスの Compare メソッドには、並べ替えを行うためのロジックが組み込まれています。

  7. アイテムを格納してある ListView コントロールを削除し、ArrayList で並べ替えたアイテムを使用して作成し直します。

  8. EndUpdate メソッドを使用して、画面描画を有効にします。

ArrayListSort メソッドで実行される並べ替えは不安定であることに注意してください。つまり、2 つの要素が等しい場合、それらの順序は保たれません。一方、安定した並べ替えの場合には、等しい要素の順序が保たれます。

アプリケーションを作成するには

  1. SortWrapper クラスをプロジェクトに追加します。このクラスには SortComparer クラスも含まれています。

    ' An instance of the SortWrapper class is created for 
    ' each item and added to the ArrayList for sorting.
    Public Class SortWrapper
        Friend sortItem As ListViewItem
        Friend sortColumn As Integer
    
        ' A SortWrapper requires the item and the index of the clicked column.
        Public Sub New(ByVal Item As ListViewItem, ByVal iColumn As Integer)
            sortItem = Item
            sortColumn = iColumn
        End Sub
    
        ' Text property for getting the text of an item.
        Public ReadOnly Property [Text]() As String
            Get
                Return sortItem.SubItems(sortColumn).Text
            End Get
        End Property
    
        ' Implementation of the IComparer 
        ' interface for sorting ArrayList items.
        Public Class SortComparer
            Implements IComparer
            Private ascending As Boolean
    
    
            ' Constructor requires the sort order;
            ' true if ascending, otherwise descending.
            Public Sub New(ByVal asc As Boolean)
                Me.ascending = asc
            End Sub
    
    
            ' Implemnentation of the IComparer:Compare 
            ' method for comparing two objects.
            Public Function [Compare](ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
                Dim xItem As SortWrapper = CType(x, SortWrapper)
                Dim yItem As SortWrapper = CType(y, SortWrapper)
    
                Dim xText As String = xItem.sortItem.SubItems(xItem.sortColumn).Text
                Dim yText As String = yItem.sortItem.SubItems(yItem.sortColumn).Text
                Return xText.CompareTo(yText) * IIf(Me.ascending, 1, -1)
            End Function
        End Class
    End Class
    
    // An instance of the SortWrapper class is created for
    // each item and added to the ArrayList for sorting.
    public class SortWrapper
    {
        internal ListViewItem sortItem;
        internal int sortColumn;
    
    
        // A SortWrapper requires the item and the index of the clicked column.
        public SortWrapper (ListViewItem Item, int iColumn)
        {
            sortItem = Item;
            sortColumn = iColumn;
        }
    
        // Text property for getting the text of an item.
        public string Text
        {
            get
            {
                return sortItem.SubItems[sortColumn].Text;
            }
        }
    
        // Implementation of the IComparer
        // interface for sorting ArrayList items.
        public class SortComparer : IComparer
        {
            bool ascending;
    
            // Constructor requires the sort order;
            // true if ascending, otherwise descending.
            public SortComparer(bool asc)
            {
                this.ascending = asc;
            }
    
            // Implemnentation of the IComparer:Compare
            // method for comparing two objects.
            public int Compare(object x, object y)
            {
                SortWrapper xItem = (SortWrapper) x;
                SortWrapper yItem = (SortWrapper) y;
    
                string xText = xItem.sortItem.SubItems[xItem.sortColumn].Text;
                string yText = yItem.sortItem.SubItems[yItem.sortColumn].Text;
                return xText.CompareTo(yText) * (this.ascending ? 1 : -1);
            }
        }
    }
    
  2. ColHeader クラスをプロジェクトに追加します。

    ' The ColHeader class is a ColumnHeader object with an 
    ' added property for determining an ascending or descending sort.
    ' True specifies an ascending order, false specifies a descending order.
    Public Class ColHeader
        Inherits ColumnHeader
        Public ascending As Boolean
    
        Public Sub New(ByVal [text] As String, ByVal width As Integer, ByVal align As HorizontalAlignment, ByVal asc As Boolean)
            Me.Text = [text]
            Me.Width = width
            Me.TextAlign = align
            Me.ascending = asc
        End Sub
    End Class
    
    // The ColHeader class is a ColumnHeader object with an
    // added property for determining an ascending or descending sort.
    // True specifies an ascending order, false specifies a descending order.
    public class ColHeader : ColumnHeader
    {
        public bool ascending;
        public ColHeader(string text, int width,  HorizontalAlignment align, bool asc)
        {
            this.Text = text;
            this.Width = width;
            this.TextAlign = align;
            this.ascending = asc;
        }
    }
    
  3. ColHeader クラスを付けて列を追加し、ListView アイテムを追加します。

    ' Set to Details view.
    Me.listView1.View = View.Details
    
    ' Add columns using the ColHeader class. The fourth    
    ' parameter specifies true for an ascending sort order.
    listView1.Columns.Add(New ColHeader("Name", 110, HorizontalAlignment.Left, True))
    listView1.Columns.Add(New ColHeader("Region", 50, HorizontalAlignment.Left, True))
    listView1.Columns.Add(New ColHeader("Sales", 70, HorizontalAlignment.Left, True))
    
    ' Add the data.
    listView1.Items.Add(New ListViewItem(New String() {"Archer, Karen", "4", "0521.28"}))
    listView1.Items.Add(New ListViewItem(New String() {"Benson, Max", "8", "0828.54"}))
    listView1.Items.Add(New ListViewItem(New String() {"Bezio, Marin", "3", "0535.22"}))
    listView1.Items.Add(New ListViewItem(New String() {"Higa, Sidney", "2", "0987.50"}))
    listView1.Items.Add(New ListViewItem(New String() {"Martin, Linda", "6", "1122.12"}))
    listView1.Items.Add(New ListViewItem(New String() {"Nash, Mike", "7", "1030.11"}))
    listView1.Items.Add(New ListViewItem(New String() {"Sanchez, Ken", "1", "0958.78"}))
    listView1.Items.Add(New ListViewItem(New String() {"Smith, Ben", "5", "0763.25"}))
    
    ' Connect the ListView.ColumnClick event to the ColumnClick event handler.
    AddHandler Me.listView1.ColumnClick, AddressOf listView1_ColumnClick
    
    this.listView1.View = View.Details;
    
    // Add columns using the ColHeader class. The fourth
    // parameter specifies true for an ascending sort order.
    listView1.Columns.Add(new ColHeader("Name", 110, HorizontalAlignment.Left, true));
    listView1.Columns.Add(new ColHeader("Region", 50, HorizontalAlignment.Left, true));
    listView1.Columns.Add(new ColHeader("Sales", 70, HorizontalAlignment.Left, true));
    
    // Add the data.
    listView1.Items.Add(new ListViewItem(new string[] {"Archer, Karen","4","0521.28"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Benson, Max","8","0828.54"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Bezio, Marin","3","0535.22"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Higa, Sidney","2","0987.50"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Martin, Linda","6","1122.12"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Nash, Mike","7","1030.11"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Sanchez, Ken","1","0958.78"}));
    listView1.Items.Add(new ListViewItem(new string[] {"Smith, Ben","5","0763.25"}));
    
    // Connect the ListView.ColumnClick event to the ColumnClick event handler.
    this.listView1.ColumnClick += new ColumnClickEventHandler(listView1_ColumnClick);
    
  4. 並べ替えを実行するためのコードを追加します。

    Private Sub listView1_ColumnClick(ByVal sender As Object, ByVal e As ColumnClickEventArgs)
    
        ' Create an instance of the ColHeader class. 
        Dim clickedCol As ColHeader = CType(Me.listView1.Columns(e.Column), ColHeader)
    
        ' Set the ascending property to sort in the opposite order.
        clickedCol.ascending = Not clickedCol.ascending
    
        ' Get the number of items in the list.
        Dim numItems As Integer = Me.listView1.Items.Count
    
        ' Turn off display while data is repoplulated.
        Me.listView1.BeginUpdate()
    
        ' Populate an ArrayList with a SortWrapper of each list item.
        Dim SortArray As New ArrayList
        Dim i As Integer
        For i = 0 To numItems - 1
            SortArray.Add(New SortWrapper(Me.listView1.Items(i), e.Column))
        Next i
    
        ' Sort the elements in the ArrayList using a new instance of the SortComparer
        ' class. The parameters are the starting index, the length of the range to sort,
        ' and the IComparer implementation to use for comparing elements. Note that
        ' the IComparer implementation (SortComparer) requires the sort  
        ' direction for its constructor; true if ascending, othwise false.
        SortArray.Sort(0, SortArray.Count, New SortWrapper.SortComparer(clickedCol.ascending))
    
        ' Clear the list, and repopulate with the sorted items.
        Me.listView1.Items.Clear()
        Dim z As Integer
        For z = 0 To numItems - 1
            Me.listView1.Items.Add(CType(SortArray(z), SortWrapper).sortItem)
        Next z
        ' Turn display back on.
        Me.listView1.EndUpdate()
    End Sub
    
    private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
    {
    
        // Create an instance of the ColHeader class.
        ColHeader clickedCol = (ColHeader)this.listView1.Columns[e.Column];
    
        // Set the ascending property to sort in the opposite order.
        clickedCol.ascending = !clickedCol.ascending;
    
        // Get the number of items in the list.
        int numItems = this.listView1.Items.Count;
    
        // Turn off display while data is repoplulated.
        this.listView1.BeginUpdate();
    
        // Populate an ArrayList with a SortWrapper of each list item.
        ArrayList SortArray = new ArrayList();
        for (int i = 0; i < numItems; i++)
        {
            SortArray.Add(new SortWrapper(this.listView1.Items[i], e.Column));
        }
    
        // Sort the elements in the ArrayList using a new instance of the SortComparer
        // class. The parameters are the starting index, the length of the range to sort,
        // and the IComparer implementation to use for comparing elements. Note that
        // the IComparer implementation (SortComparer) requires the sort
        // direction for its constructor; true if ascending, othwise false.
        SortArray.Sort(0, SortArray.Count, new SortWrapper.SortComparer(clickedCol.ascending));
    
        // Clear the list, and repopulate with the sorted items.
        this.listView1.Items.Clear();
        for  (int i = 0; i < numItems; i++)
            this.listView1.Items.Add(((SortWrapper)SortArray[i]).sortItem);
    
        // Turn display back on.
        this.listView1.EndUpdate();
    }
    

コードのコンパイル方法

この例では、次の名前空間への参照が必要です。

参照

概念

カスタム コントロールの開発

.NET Compact Framework に関する「方法」トピック

その他の技術情報

.NET Compact Framework の Windows フォーム コントロール