How can I display a sort arrow in the header of the sorted column in a list view which follows the native look of the operating system?
views:
2968answers:
2
+17
A:
You can use the following extension method to set the sort arrow to a particular column:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public static class ListViewExtensions
{
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct LVCOLUMN
{
public Int32 mask;
public Int32 cx;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.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;
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessage")]
private static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, Int32 Msg, IntPtr wParam, ref LVCOLUMN lPLVCOLUMN);
public static void SetSortIcon(this System.Windows.Forms.ListView ListViewControl, int ColumnIndex, System.Windows.Forms.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 == System.Windows.Forms.SortOrder.None) && ColumnNumber == ColumnIndex)
{
switch (Order)
{
case System.Windows.Forms.SortOrder.Ascending:
lvColumn.fmt &= ~HDF_SORTDOWN;
lvColumn.fmt |= HDF_SORTUP;
break;
case System.Windows.Forms.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);
}
}
}
Then, you can call the extension method like such:
myListView.SetSortIcon(0, SortOrder.Ascending);
Andrew Moore
2008-10-31 16:38:00
Note that Application.EnableVisualStyles(); must be called for the code above to work.
Rune
2008-12-01 18:26:57
No it doesn't. It works as well for unstyled ListViews.
Andrew Moore
2009-01-02 19:55:29
The LVCOLUMN you defined is actually HDITEM. I realize since you define it yourself that it doesn't matter, but when translating that into C++ it confused me for a few :).
Bob
2009-10-26 18:10:37
+1: Almost a year and a half later, and I find this. Great work, many thanks!
Codesleuth
2010-02-04 10:30:12