43

オペレーティング システムのネイティブの外観に従うリスト ビューで、並べ替えられた列のヘッダーに並べ替え矢印を表示するにはどうすればよいですか?

4

4 に答える 4

73

次の拡張メソッドを使用して、ソート矢印を特定の列に設定できます。

[EditorBrowsable(EditorBrowsableState.Never)]
public static class ListViewExtensions
{
    [StructLayout(LayoutKind.Sequential)]
    public struct HDITEM
    {
        public Mask mask;
        public int cxy;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszText;
        public IntPtr hbm;
        public int cchTextMax;
        public Format fmt;
        public IntPtr lParam;
        // _WIN32_IE >= 0x0300 
        public int iImage;
        public int iOrder;
        // _WIN32_IE >= 0x0500
        public uint type;
        public IntPtr pvFilter;
        // _WIN32_WINNT >= 0x0600
        public uint state;

        [Flags]
        public enum Mask
        {
            Format = 0x4,       // HDI_FORMAT
        };

        [Flags]
        public enum Format
        {
            SortDown = 0x200,   // HDF_SORTDOWN
            SortUp = 0x400,     // HDF_SORTUP
        };
    };

    public const int LVM_FIRST = 0x1000;
    public const int LVM_GETHEADER = LVM_FIRST + 31;

    public const int HDM_FIRST = 0x1200;
    public const int HDM_GETITEM = HDM_FIRST + 11;
    public const int HDM_SETITEM = HDM_FIRST + 12;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref HDITEM lParam);

    public static void SetSortIcon(this ListView listViewControl, int columnIndex, SortOrder order)
    {
        IntPtr columnHeader = SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
        for (int columnNumber = 0; columnNumber <= listViewControl.Columns.Count - 1; columnNumber++)
        {
            var columnPtr = new IntPtr(columnNumber);
            var item = new HDITEM
                {
                    mask = HDITEM.Mask.Format
                };

            if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero)
            {
                throw new Win32Exception();
            }

            if (order != SortOrder.None && columnNumber == columnIndex)
            {
                switch (order)
                {
                    case SortOrder.Ascending:
                        item.fmt &= ~HDITEM.Format.SortDown;
                        item.fmt |= HDITEM.Format.SortUp;
                        break;
                    case SortOrder.Descending:
                        item.fmt &= ~HDITEM.Format.SortUp;
                        item.fmt |= HDITEM.Format.SortDown;
                        break;
                }
            }
            else
            {
                item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp;
            }

            if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero)
            {
                throw new Win32Exception();
            }
        }
    }
}

次に、次のように拡張メソッドを呼び出すことができます。

myListView.SetSortIcon(0, SortOrder.Ascending);

P/Invoke を使用して動作します。

  • LVM_GETHEADERメッセージを使用して、リスト ビューのヘッダー コントロールへのハンドルを取得します。
  • HDM_GETITEMメッセージを使用してヘッダー列に関する情報を取得します。
  • 次に、返されたHDITEM構造体のフラグとフラグfmtを設定/クリアするように変更します。HDF_SORTDOWNHDF_SORTUP
  • 最後に、 HDM_SETITEMメッセージを使用して情報を再設定します。

これは次のようになります。

リスト ビュー列の矢印

于 2008-10-31T16:38:00.710 に答える