Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. ListView Column Sort Arrow

ListView Column Sort Arrow

Scheduled Pinned Locked Moved C#
helpcsharpquestion
10 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • realJSOPR Online
    realJSOPR Online
    realJSOP
    wrote on last edited by
    #1

    Using DotNet 3.5... I found the following code on the net (I don't remember exactly where, but I do know it's conglomeration of a couple of different examples). It's a ListView extension method that's responsible for putting a sort direction arrow in the column header. The problem is that it places the arrow above the column header text and centers the arrow in the column. I've made a couple of attempts to try to get the arrow to be laced on the right side of the column, but nothing has worked. My last attempt was to add the line after the switch(order) statement that adds the HDF_BITMAP_ON_RIGHT flag. Can anyone help?

    [EditorBrowsable(EditorBrowsableState.Never)]
    public static class ListViewExtensions
    {
    [StructLayout(LayoutKind.Sequential)]
    protected struct LVCOLUMN
    {
    public Int32 mask;
    public Int32 cx;
    [MarshalAs(UnmanagedType.LPTStr)]
    public string pszText;
    public IntPtr hbm;
    public Int32 cchTextMax;
    public Int32 fmt;
    public Int32 iSubItem;
    public Int32 iImage;
    public Int32 iOrder;
    }

    const Int32 HDI\_WIDTH           = 0x0001;
    const Int32 HDI\_HEIGHT          = HDI\_WIDTH;
    const Int32 HDI\_TEXT            = 0x0002;
    const Int32 HDI\_FORMAT          = 0x0004;
    const Int32 HDI\_LPARAM          = 0x0008;
    const Int32 HDI\_BITMAP          = 0x0010;
    const Int32 HDI\_IMAGE           = 0x0020;
    const Int32 HDI\_DI\_SETITEM      = 0x0040;
    const Int32 HDI\_ORDER           = 0x0080;
    const Int32 HDI\_FILTER          = 0x0100;
    
    const Int32 HDF\_LEFT            = 0x0000;
    const Int32 HDF\_RIGHT           = 0x0001;
    const Int32 HDF\_CENTER          = 0x0002;
    const Int32 HDF\_JUSTIFYMASK     = 0x0003;
    const Int32 HDF\_RTLREADING      = 0x0004;
    const Int32 HDF\_OWNERDRAW       = 0x8000;
    const Int32 HDF\_STRING          = 0x4000;
    const Int32 HDF\_BITMAP          = 0x2000;
    const Int32 HDF\_BITMAP\_ON\_RIGHT = 0x1000;
    const Int32 HDF\_IMAGE           = 0x0800;
    const Int32 HDF\_SORTUP          = 0x0400;
    const Int32 HDF\_SORTDOWN        = 0x0200;
    
    const Int32 LVM\_FIRST           = 0x1000;         // List messages
    const Int32 LVM\_GETHEADER       = LVM\_FIRST + 31;
    const Int32 HDM\_FIRST           = 0x1200;         // Header messages
    const Int32 HDM\_SETIMAGELIST    = HDM\_FIRST + 8;
    const Int32 HDM\_GETIMAGELIST    = HDM\_FIRST + 9;
    const Int32 HDM\_GETITEM
    
    P T 2 Replies Last reply
    0
    • realJSOPR realJSOP

      Using DotNet 3.5... I found the following code on the net (I don't remember exactly where, but I do know it's conglomeration of a couple of different examples). It's a ListView extension method that's responsible for putting a sort direction arrow in the column header. The problem is that it places the arrow above the column header text and centers the arrow in the column. I've made a couple of attempts to try to get the arrow to be laced on the right side of the column, but nothing has worked. My last attempt was to add the line after the switch(order) statement that adds the HDF_BITMAP_ON_RIGHT flag. Can anyone help?

      [EditorBrowsable(EditorBrowsableState.Never)]
      public static class ListViewExtensions
      {
      [StructLayout(LayoutKind.Sequential)]
      protected struct LVCOLUMN
      {
      public Int32 mask;
      public Int32 cx;
      [MarshalAs(UnmanagedType.LPTStr)]
      public string pszText;
      public IntPtr hbm;
      public Int32 cchTextMax;
      public Int32 fmt;
      public Int32 iSubItem;
      public Int32 iImage;
      public Int32 iOrder;
      }

      const Int32 HDI\_WIDTH           = 0x0001;
      const Int32 HDI\_HEIGHT          = HDI\_WIDTH;
      const Int32 HDI\_TEXT            = 0x0002;
      const Int32 HDI\_FORMAT          = 0x0004;
      const Int32 HDI\_LPARAM          = 0x0008;
      const Int32 HDI\_BITMAP          = 0x0010;
      const Int32 HDI\_IMAGE           = 0x0020;
      const Int32 HDI\_DI\_SETITEM      = 0x0040;
      const Int32 HDI\_ORDER           = 0x0080;
      const Int32 HDI\_FILTER          = 0x0100;
      
      const Int32 HDF\_LEFT            = 0x0000;
      const Int32 HDF\_RIGHT           = 0x0001;
      const Int32 HDF\_CENTER          = 0x0002;
      const Int32 HDF\_JUSTIFYMASK     = 0x0003;
      const Int32 HDF\_RTLREADING      = 0x0004;
      const Int32 HDF\_OWNERDRAW       = 0x8000;
      const Int32 HDF\_STRING          = 0x4000;
      const Int32 HDF\_BITMAP          = 0x2000;
      const Int32 HDF\_BITMAP\_ON\_RIGHT = 0x1000;
      const Int32 HDF\_IMAGE           = 0x0800;
      const Int32 HDF\_SORTUP          = 0x0400;
      const Int32 HDF\_SORTDOWN        = 0x0200;
      
      const Int32 LVM\_FIRST           = 0x1000;         // List messages
      const Int32 LVM\_GETHEADER       = LVM\_FIRST + 31;
      const Int32 HDM\_FIRST           = 0x1200;         // Header messages
      const Int32 HDM\_SETIMAGELIST    = HDM\_FIRST + 8;
      const Int32 HDM\_GETIMAGELIST    = HDM\_FIRST + 9;
      const Int32 HDM\_GETITEM
      
      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      using System;
      using System.Collections.Generic;
      using System.Text;
      using System.Windows.Forms;
      using System.ComponentModel;

      namespace JSOPTest
      {
      [EditorBrowsable(EditorBrowsableState.Never)]
      public static class ExListView
      {
      [StructLayout(LayoutKind.Sequential)]
      private struct LVCOLUMN
      {
      public Int32 mask;
      public Int32 cx;
      [MarshalAs(UnmanagedType.LPTStr)]
      public string pszText;
      public IntPtr hbm;
      public Int32 cchTextMax;
      public Int32 fmt;
      public Int32 iSubItem;
      public Int32 iImage;
      public Int32 iOrder;
      }

      private const Int32 HDI\_FORMAT = 0x4;
      private const Int32 HDF\_SORTUP = 0x400;
      private const Int32 HDF\_SORTDOWN = 0x200;
      private const Int32 LVM\_GETHEADER = 0x101f;
      private const Int32 HDM\_GETITEM = 0x120b;
      private const Int32 HDM\_SETITEM = 0x120c;
      
      \[DllImport("user32.dll")\]
      private static extern IntPtr SendMessage(
          IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
      
      \[DllImport("user32.dll", EntryPoint = "SendMessage")\]
      private static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, 
          Int32 Msg, 
          IntPtr wParam, 
          ref LVCOLUMN lPLVCOLUMN);
      
      public static void SetSortIcon(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++)
        {
          IntPtr ColumnPtr = new IntPtr(ColumnNumber);
          LVCOLUMN lvColumn = new LVCOLUMN();
          lvColumn.mask = HDI\_FORMAT;
          SendMessageLVCOLUMN(ColumnHeader, HDM\_GETITEM, ColumnPtr, ref lvColumn);
      
          if (!(Order ==   SortOrder.None) && ColumnNumber == ColumnIndex)
          {
            switch (Order)
            {
              case   SortOrder.Ascending:
                lvColumn.fmt &= ~HDF\_SORTDOWN;
                lvColumn.fmt |= HDF\_SORTUP;
                break;
              case   SortOrder.Descending:
                lvColumn.fmt &= ~HDF\_SORTUP;
                lvColumn.fmt |= HDF\_SORTDOWN;
                break;
            }
          }
          else
          {
            lvColumn.fmt &= ~HDF\_SORTDOWN & ~HDF\_SORTUP;
          }
      
          SendMessageLVCOLUMN(ColumnHeader, HDM\_SETITEM, ColumnPtr, ref lvColumn);
        }
      }
      

      }

      }

      realJSOPR 1 Reply Last reply
      0
      • P Pete OHanlon

        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Windows.Forms;
        using System.ComponentModel;

        namespace JSOPTest
        {
        [EditorBrowsable(EditorBrowsableState.Never)]
        public static class ExListView
        {
        [StructLayout(LayoutKind.Sequential)]
        private struct LVCOLUMN
        {
        public Int32 mask;
        public Int32 cx;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string pszText;
        public IntPtr hbm;
        public Int32 cchTextMax;
        public Int32 fmt;
        public Int32 iSubItem;
        public Int32 iImage;
        public Int32 iOrder;
        }

        private const Int32 HDI\_FORMAT = 0x4;
        private const Int32 HDF\_SORTUP = 0x400;
        private const Int32 HDF\_SORTDOWN = 0x200;
        private const Int32 LVM\_GETHEADER = 0x101f;
        private const Int32 HDM\_GETITEM = 0x120b;
        private const Int32 HDM\_SETITEM = 0x120c;
        
        \[DllImport("user32.dll")\]
        private static extern IntPtr SendMessage(
            IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        
        \[DllImport("user32.dll", EntryPoint = "SendMessage")\]
        private static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, 
            Int32 Msg, 
            IntPtr wParam, 
            ref LVCOLUMN lPLVCOLUMN);
        
        public static void SetSortIcon(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++)
          {
            IntPtr ColumnPtr = new IntPtr(ColumnNumber);
            LVCOLUMN lvColumn = new LVCOLUMN();
            lvColumn.mask = HDI\_FORMAT;
            SendMessageLVCOLUMN(ColumnHeader, HDM\_GETITEM, ColumnPtr, ref lvColumn);
        
            if (!(Order ==   SortOrder.None) && ColumnNumber == ColumnIndex)
            {
              switch (Order)
              {
                case   SortOrder.Ascending:
                  lvColumn.fmt &= ~HDF\_SORTDOWN;
                  lvColumn.fmt |= HDF\_SORTUP;
                  break;
                case   SortOrder.Descending:
                  lvColumn.fmt &= ~HDF\_SORTUP;
                  lvColumn.fmt |= HDF\_SORTDOWN;
                  break;
              }
            }
            else
            {
              lvColumn.fmt &= ~HDF\_SORTDOWN & ~HDF\_SORTUP;
            }
        
            SendMessageLVCOLUMN(ColumnHeader, HDM\_SETITEM, ColumnPtr, ref lvColumn);
          }
        }
        

        }

        }

        realJSOPR Online
        realJSOPR Online
        realJSOP
        wrote on last edited by
        #3

        That's what I started out with. It gives me the sort arrow, but it's positioned above the text, and centered horizontally in the column header. Mine is different only with respect the extra const members, the renaming of some of the variables using in the extension method, and the attempted use of the extra flag after the switch statement. On a side note, I don't understand why Microsoft would omit this feature (and others) from the list control in the first place. Programmers have always need to add extra code to implement stuff that should - by now - be part of the control itself.

        .45 ACP - because shooting twice is just silly
        -----
        "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
        -----
        "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

        P 1 Reply Last reply
        0
        • realJSOPR realJSOP

          That's what I started out with. It gives me the sort arrow, but it's positioned above the text, and centered horizontally in the column header. Mine is different only with respect the extra const members, the renaming of some of the variables using in the extension method, and the attempted use of the extra flag after the switch statement. On a side note, I don't understand why Microsoft would omit this feature (and others) from the list control in the first place. Programmers have always need to add extra code to implement stuff that should - by now - be part of the control itself.

          .45 ACP - because shooting twice is just silly
          -----
          "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
          -----
          "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

          P Offline
          P Offline
          Pete OHanlon
          wrote on last edited by
          #4

          That's kind of odd because this is code I ripped out of an old winforms project that I have, and it gave the arrow where you'd expect it. Granted it was a .NET 2 project, but I don't see that as having an effect.

          "WPF has many lovers. It's a veritable porn star!" - Josh Smith

          As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

          My blog | My articles | MoXAML PowerToys | Onyx

          realJSOPR 2 Replies Last reply
          0
          • P Pete OHanlon

            That's kind of odd because this is code I ripped out of an old winforms project that I have, and it gave the arrow where you'd expect it. Granted it was a .NET 2 project, but I don't see that as having an effect.

            "WPF has many lovers. It's a veritable porn star!" - Josh Smith

            As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

            My blog | My articles | MoXAML PowerToys | Onyx

            realJSOPR Online
            realJSOPR Online
            realJSOP
            wrote on last edited by
            #5

            I even thought it might have something to do with the orientation of the header text, so I made them all Left, but that didn't have any effect either.

            .45 ACP - because shooting twice is just silly
            -----
            "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
            -----
            "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

            1 Reply Last reply
            0
            • P Pete OHanlon

              That's kind of odd because this is code I ripped out of an old winforms project that I have, and it gave the arrow where you'd expect it. Granted it was a .NET 2 project, but I don't see that as having an effect.

              "WPF has many lovers. It's a veritable porn star!" - Josh Smith

              As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

              My blog | My articles | MoXAML PowerToys | Onyx

              realJSOPR Online
              realJSOPR Online
              realJSOP
              wrote on last edited by
              #6

              I created a new project with an unmolested listview control, dropped the code into it, and it still does it. Could it be a Windows 7 thing?

              .45 ACP - because shooting twice is just silly
              -----
              "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
              -----
              "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

              P 2 Replies Last reply
              0
              • realJSOPR realJSOP

                I created a new project with an unmolested listview control, dropped the code into it, and it still does it. Could it be a Windows 7 thing?

                .45 ACP - because shooting twice is just silly
                -----
                "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
                -----
                "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

                P Offline
                P Offline
                Pete OHanlon
                wrote on last edited by
                #7

                Possibly. I'll try it out later on.

                "WPF has many lovers. It's a veritable porn star!" - Josh Smith

                As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

                My blog | My articles | MoXAML PowerToys | Onyx

                1 Reply Last reply
                0
                • realJSOPR realJSOP

                  I created a new project with an unmolested listview control, dropped the code into it, and it still does it. Could it be a Windows 7 thing?

                  .45 ACP - because shooting twice is just silly
                  -----
                  "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
                  -----
                  "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

                  P Offline
                  P Offline
                  Pete OHanlon
                  wrote on last edited by
                  #8

                  It's a Windows 7 thing. The icon in Windows 7 appears centred above the text.

                  "WPF has many lovers. It's a veritable porn star!" - Josh Smith

                  As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

                  My blog | My articles | MoXAML PowerToys | Onyx

                  1 Reply Last reply
                  0
                  • realJSOPR realJSOP

                    Using DotNet 3.5... I found the following code on the net (I don't remember exactly where, but I do know it's conglomeration of a couple of different examples). It's a ListView extension method that's responsible for putting a sort direction arrow in the column header. The problem is that it places the arrow above the column header text and centers the arrow in the column. I've made a couple of attempts to try to get the arrow to be laced on the right side of the column, but nothing has worked. My last attempt was to add the line after the switch(order) statement that adds the HDF_BITMAP_ON_RIGHT flag. Can anyone help?

                    [EditorBrowsable(EditorBrowsableState.Never)]
                    public static class ListViewExtensions
                    {
                    [StructLayout(LayoutKind.Sequential)]
                    protected struct LVCOLUMN
                    {
                    public Int32 mask;
                    public Int32 cx;
                    [MarshalAs(UnmanagedType.LPTStr)]
                    public string pszText;
                    public IntPtr hbm;
                    public Int32 cchTextMax;
                    public Int32 fmt;
                    public Int32 iSubItem;
                    public Int32 iImage;
                    public Int32 iOrder;
                    }

                    const Int32 HDI\_WIDTH           = 0x0001;
                    const Int32 HDI\_HEIGHT          = HDI\_WIDTH;
                    const Int32 HDI\_TEXT            = 0x0002;
                    const Int32 HDI\_FORMAT          = 0x0004;
                    const Int32 HDI\_LPARAM          = 0x0008;
                    const Int32 HDI\_BITMAP          = 0x0010;
                    const Int32 HDI\_IMAGE           = 0x0020;
                    const Int32 HDI\_DI\_SETITEM      = 0x0040;
                    const Int32 HDI\_ORDER           = 0x0080;
                    const Int32 HDI\_FILTER          = 0x0100;
                    
                    const Int32 HDF\_LEFT            = 0x0000;
                    const Int32 HDF\_RIGHT           = 0x0001;
                    const Int32 HDF\_CENTER          = 0x0002;
                    const Int32 HDF\_JUSTIFYMASK     = 0x0003;
                    const Int32 HDF\_RTLREADING      = 0x0004;
                    const Int32 HDF\_OWNERDRAW       = 0x8000;
                    const Int32 HDF\_STRING          = 0x4000;
                    const Int32 HDF\_BITMAP          = 0x2000;
                    const Int32 HDF\_BITMAP\_ON\_RIGHT = 0x1000;
                    const Int32 HDF\_IMAGE           = 0x0800;
                    const Int32 HDF\_SORTUP          = 0x0400;
                    const Int32 HDF\_SORTDOWN        = 0x0200;
                    
                    const Int32 LVM\_FIRST           = 0x1000;         // List messages
                    const Int32 LVM\_GETHEADER       = LVM\_FIRST + 31;
                    const Int32 HDM\_FIRST           = 0x1200;         // Header messages
                    const Int32 HDM\_SETIMAGELIST    = HDM\_FIRST + 8;
                    const Int32 HDM\_GETIMAGELIST    = HDM\_FIRST + 9;
                    const Int32 HDM\_GETITEM
                    
                    T Offline
                    T Offline
                    tusk
                    wrote on last edited by
                    #9

                    Hi! The extention method works pretty good. (I'm on XP and it's on the right of the text) Does anyone know, if there's any chance to set the flag

                    lvcolumn.fmt |= HDF_BITMAP|HDF_BITMAP_ON_RIGHT;

                    instead of

                    lvColumn.fmt &= ~HDF_SORTDOWN;
                    lvColumn.fmt |= HDF_SORTUP;

                    and then load a picture (from the C# .resx file for instance) ?? I would like to use the same exact extention, but drawing a custom arrow of my own instead of the system's arrow ... any help appreciated ;)

                    T 1 Reply Last reply
                    0
                    • T tusk

                      Hi! The extention method works pretty good. (I'm on XP and it's on the right of the text) Does anyone know, if there's any chance to set the flag

                      lvcolumn.fmt |= HDF_BITMAP|HDF_BITMAP_ON_RIGHT;

                      instead of

                      lvColumn.fmt &= ~HDF_SORTDOWN;
                      lvColumn.fmt |= HDF_SORTUP;

                      and then load a picture (from the C# .resx file for instance) ?? I would like to use the same exact extention, but drawing a custom arrow of my own instead of the system's arrow ... any help appreciated ;)

                      T Offline
                      T Offline
                      tusk
                      wrote on last edited by
                      #10

                      Edit: It works well with _IMAGE instead of _SORTDOWN or _SORTUP Only problem is that it will remove the other image on the column header (if you dont have any image in your column header, then it's all fine, but if you do, like in my project, well it will be either on the left, or on the right as a sort indicator, but not both. My plan was to leave a column header image on the left, and a small arrow on the right......) Will need to owner draw the full header :/ That's bad because column header's mouse over event are pretty hard to catch.. dont even know how to do so far...... Anyway, if someone has a clue.. :)

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups