R – How to set the header sort glyph in a .NET ListView

glyphheaderlistviewsortingthemes

How do I set the column which has the header sort glyph, and its direction, in a .NET 2.0 WinForms ListView?

Bump

The listview is .net is not a managed control, it is a very thin wrapper around the Win32 ListView common control. It's not even a very good wrapper – it doesn't expose all the features of the real listview.

The Win32 listview common control supports drawing itself with themes. One of the themed elements is the header sort arrow. Windows Explorer's listview common control knows how to draw one of its columns with that theme element.

  • does the Win32 listview support specifying which column has what sort order?
  • does the Win32 header control that the listview internally uses support specifying which column has what sort order?
  • does the win32 header control support custom drawing, so I can draw the header sort glyph myself?
  • does the win32 listview control support custom header drawing, so I can draw the header sort glyph myself?
  • does the .NET ListView control support custom header drawing, so I can draw the header sort glyph myself?

Best Answer

In case someone needs a quick solution (it draws up/down arrow at the beginning of column header text):

ListViewExtensions.cs:

public static class ListViewExtensions
{
    public static void DrawSortArrow(this ListView listView, SortOrder sortOrder, int colIndex)
    {
        string upArrow = "▲   ";
        string downArrow = "▼   ";

        foreach (ColumnHeader ch in listView.Columns)
        {
            if (ch.Text.Contains(upArrow))
                ch.Text = ch.Text.Replace(upArrow, string.Empty);
            else if (ch.Text.Contains(downArrow))
                ch.Text = ch.Text.Replace(downArrow, string.Empty);
        }

        if (sortOrder == SortOrder.Ascending)
            listView.Columns[colIndex].Text = listView.Columns[colIndex].Text.Insert(0, downArrow);
        else
            listView.Columns[colIndex].Text = listView.Columns[colIndex].Text.Insert(0, upArrow);
    }
}

Usage:

private void lstOffers_ColumnClick(object sender, ColumnClickEventArgs e)
{
    lstOffers.DrawSortArrow(SortOrder.Descending, e.Column);
}