2009-06-25 10 views
1

Dans l'Explorateur Windows XP et Vista, lorsque vous faites un tri par colonne lorsque le ListView est en mode Détails, l'arrière-plan de la colonne est mis en surbrillance pour indiquer que la colonne est triée. Une flèche pour la direction du tri est également affichée dans l'en-tête de la colonne. Quelles sont les meilleures pratiques pour atteindre ces effets dans votre propre application Windows Forms?Affichage visuel du tri dans un contrôle ListView

Répondre

3

Cette méthode émule le style de sélection "Windows XP". Vista et Win7 utilisent des fonctionnalités étendues de ListViews, qui n'est pas (encore?) Présent dans .NET. Si nécessaire, cela peut être fait en utilisant Interop.

Voici comment faire:

  1. Créer un ImageList qui contient les images suivantes: 0: vide, 1: "up" et 2: "down"

    • Affectez ImageList à votre propriété ListView.SmallImageList
    • Chaque fois que vous ajoutez un élément dans le ListView, assurez-vous que ses UseItemStyleForSubItems est réglé sur « false »
    • Ajoutez le code de tri à votre application, qui est décrit here
    • Dans le code que vous venez d'ajouter, remplacer le gestionnaire ColumnClick avec le code suivant (l'instance ListView ici est appelé "_list"):

      vide _List_ColumnClick (expéditeur d'objet, ColumnClickEventArgs e) { _List.SuspendLayout(); if (e.Column == lvwColumnSorter.SortColumn) {// la colonne précédemment triée sera retournée if (lvwColumnSorter.Order == SortOrder.Ascending) { lvwColumnSorter.Order = SortOrder.Descending; } else { lvwColumnSorter.Order = SortOrder.Ascending; } } else {// la nouvelle colonne sera triée _List.Columns [lvwColumnSorter.SortColumn] .ImageIndex = 0; foreach (ListViewItem lvi dans _List.Items) { lvi.SubItems [lvwColumnSorter.SortColumn] .BackColor = SystemColors.Window; } lvwColumnSorter.SortColumn = e.Colonne; lvwColumnSorter.Order = SortOrder.Ascending; } _List.Sort(); _List.Columns [e.Column] .ImageIndex = lvwColumnSorter.Order == SortOrder.Ascending? 1: 2; foreach (ListViewItem lvi dans _List.Items) { lvi.SubItems [e.Column] .BackColor = SystemColors.Info; // c'est la couleur utilisée pour le suivi } _List.ResumeLayout(); }


Edit:

est Ci-dessous l'approche 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

Avez-vous l'approche Interop à portée de main? –

+0

Maintenant, je fais: ajouté à la réponse. L'exemple de code montre comment Interop est effectué et les messages et les constantes sont extraits des fichiers d'en-tête SDK, avec l'aide de MSDN et du moteur de recherche. – Rom

Questions connexes