Визуально показывает сортировку в элементе управления ListView - PullRequest
1 голос
/ 25 июня 2009

В проводнике Windows в XP и Vista при сортировке по столбцу, когда ListView находится в режиме «Сведения», фон столбца подсвечивается, чтобы указать, что столбец сортируется. Стрелка для направления сортировки также отображается в заголовке столбца. Каковы наилучшие методы для достижения этих эффектов в вашем собственном приложении Windows Forms?

1 Ответ

3 голосов
/ 25 июня 2009

Этот метод эмулирует стиль выделения «Windows XP». Vista и Win7 используют расширенную функциональность ListViews, которой нет (пока?) В .NET. При необходимости это можно сделать с помощью Interop.

Вот как это сделать:

  1. Создайте ImageList, который содержит следующие изображения: 0: пусто, 1: «вверх» и 2: «вниз»

    • Назначьте этот ImageList для вашего свойства ListView.SmallImageList
    • Каждый раз, когда вы добавляете элемент в ListView, убедитесь, что его UseItemStyleForSubItems имеет значение «false»
    • Добавьте код сортировки в ваше приложение, описание которого здесь
    • В коде, который вы только что добавили, замените обработчик ColumnClick следующим кодом (экземпляр ListView здесь называется "_List"):

      void _List_ColumnClick (отправитель объекта, ColumnClickEventArgs e) { _List.SuspendLayout (); if (e.Column == lvwColumnSorter.SortColumn) {// ранее отсортированный столбец будет перевернут if (lvwColumnSorter.Order == SortOrder.Ascending) { lvwColumnSorter.Order = SortOrder.Descending; } еще { lvwColumnSorter.Order = SortOrder.Ascending; } } else {// новый столбец будет отсортирован _List.Columns [lvwColumnSorter.SortColumn] .ImageIndex = 0; foreach (ListViewItem lvi в _List.Items) { lvi.SubItems [lvwColumnSorter.SortColumn] .BackColor = SystemColors.Window; } lvwColumnSorter.SortColumn = e.Column; lvwColumnSorter.Order = SortOrder.Ascending; } _List.Sort (); _List.Columns [e.Column] .ImageIndex = lvwColumnSorter.Order == SortOrder.Ascending? 1: 2; foreach (ListViewItem lvi в _List.Items) { lvi.SubItems [e.Column] .BackColor = SystemColors.Info; // это цвет, используемый для отслеживания } _List.ResumeLayout (); }


Edit:

Ниже приведен подход взаимодействия:

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, uint message, UIntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, uint message, UIntPtr wParam, ref HDITEM lParam);

    public enum WM {
        LVM_FIRST = 0x1000,      // ListView messages
        // ...
        LVM_GETHEADER = LVM_FIRST + 31,
        // ...
        HDM_FIRST = 0x1200,      // Header messages
        // ...
        HDM_SETITEM = HDM_FIRST + 12,
        // ...
        HDM_SETFOCUSEDITEM = HDM_FIRST + 28,
    }
    public enum HDI {
        HDI_WIDTH = 0x0001,
        HDI_HEIGHT = HDI_WIDTH,
        HDI_TEXT = 0x0002,
        HDI_FORMAT = 0x0004,
        HDI_LPARAM = 0x0008,
        HDI_BITMAP = 0x0010,
        HDI_IMAGE = 0x0020,
        HDI_DI_SETITEM = 0x0040,
        HDI_ORDER = 0x0080,
        HDI_FILTER = 0x0100,
        HDI_STATE = 0x0200
    }
    public enum HDF {
        HDF_LEFT                = 0x0000,
        HDF_RIGHT               = 0x0001,
        HDF_CENTER              = 0x0002,
        HDF_JUSTIFYMASK         = 0x0003,
        HDF_RTLREADING          = 0x0004,
        HDF_BITMAP              = 0x2000,
        HDF_STRING              = 0x4000,
        HDF_OWNERDRAW           = 0x8000,
        HDF_IMAGE               = 0x0800,
        HDF_BITMAP_ON_RIGHT     = 0x1000,
        HDF_SORTUP              = 0x0400,
        HDF_SORTDOWN            = 0x0200,
        HDF_CHECKBOX            = 0x0040,
        HDF_CHECKED             = 0x0080,
        HDF_FIXEDWIDTH          = 0x0100,
        HDF_SPLITBUTTON      = 0x1000000
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct HDITEM {
        public uint mask;
        public int cxy;
        public String pszText;
        public IntPtr hbm;
        public int cchTextMax;
        public int fmt;
        public IntPtr lParam;
        public int iImage;
        public int iOrder;
        public uint type;
        public IntPtr pvFilter; // this is void*
        public uint state;
    }


    void _List_ColumnClick(object sender, ColumnClickEventArgs e) {
        _List.SuspendLayout();
        HDITEM hdi = new HDITEM();
        hdi.mask = (uint)HDI.HDI_FORMAT;
        hdi.fmt = (int)HDF.HDF_STRING;
        IntPtr hHeader = (IntPtr)SendMessage(_List.Handle, (uint)WM.LVM_GETHEADER, (UIntPtr)0, (IntPtr)0);
        if (e.Column == lvwColumnSorter.SortColumn) { // the column previously sorted will be flipped
            if (lvwColumnSorter.Order == SortOrder.Ascending) {
                lvwColumnSorter.Order = SortOrder.Descending;
            } else {
                lvwColumnSorter.Order = SortOrder.Ascending;
            }
        } else {    // new column will be sorted
            SendMessage((IntPtr)hHeader, (uint)WM.HDM_SETITEM, (UIntPtr)lvwColumnSorter.SortColumn, ref hdi);
            foreach (ListViewItem lvi in _List.Items) {
                lvi.SubItems[lvwColumnSorter.SortColumn].BackColor = SystemColors.Window;
            }
            lvwColumnSorter.SortColumn = e.Column;
            lvwColumnSorter.Order = SortOrder.Ascending;
        }
        _List.Sort();
        hdi.fmt |= (lvwColumnSorter.Order == SortOrder.Ascending ? (int)HDF.HDF_SORTDOWN : (int)HDF.HDF_SORTUP);
        SendMessage((IntPtr)hHeader, (uint)WM.HDM_SETITEM, (UIntPtr)e.Column, ref hdi);
        foreach (ListViewItem lvi in _List.Items) {
            lvi.SubItems[e.Column].BackColor = SystemColors.Info; // this is the color used for tracking
        }
        _List.ResumeLayout();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...