2009-06-25 4 views
1

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

ответ

3

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

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

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

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

      недействительным _List_ColumnClick (объект отправителя, ColumnClickEventArgs e) { _List.SuspendLayout(); if (e.Column == lvwColumnSorter.SortColumn) {// отсортированный столбец будет перевернут if (lvwColumnSorter.Order == SortOrder.Ascending) { lvwColumnSorter.Order = SortOrder.Descending; } else { lvwColumnSorter.Order = SortOrder.Ascending; } } else {// новый столбец будет отсортирован _List.Columns [lvwColumnSorter.SortColumn] .ImageIndex = 0; foreach (ListViewItem lvi in ​​_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 in ​​_List.Items) { lvi.SubItems [e.Column] .BackColor = SystemColors.Info; // это цвет, используемый для отслеживания } _List.ResumeLayout(); }


Edit:

Ниже Interop подход:

[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(); 
    } 
+0

Есть ли у вас подход Interop под рукой? –

+0

Теперь я делаю: добавил к ответу. Пример кода показывает, как выполняется Interop, а сообщения и константы берутся из файлов заголовков SDK с некоторой помощью из MSDN и поисковой системы. – Rom

Смежные вопросы