Sorting the list when user clicks on column header


If you dont want to allow the users to sort the list by clicking on the header, you can use the style LVS_NOSORTHEADER. However, if you do want to allow sorting, you do not specify the LVS_NOSORTHEADER. The control, though, does not sort the items. You have to handle the HDN_ITEMCLICK notification from the header control and process it appropriately. In the code below, we have used the sorting function SortTextItems() developed in a previous section. You may choose to sort the items in a different manner.

Step 1: Add two member variables

Add two member variables to the CListCtrl. The first variable to track which column has been sorted on, if any. The second variable to track if the sort is ascending or descending.

        int nSortedCol;
        BOOL bSortAscending;
 

Step 2: Initialize them in the constructor.

Initialize nSortedCol to -1 to indicate that no column has been sorted on. If the list is initially sorted, then this variable should reflect that.
 
        nSortedCol = -1;
        bSortAscending = TRUE;
 

Step 3: Add entry in message map to handle HDN_ITEMCLICK

Actually you need to add two entries. For HDN_ITEMCLICKA and HDN_ITEMCLICKW. Do not use the class wizard to add the entry. For one, you need to add two entries whereas the class wizard will allow you only one. Secondly, the class wizard uses the wrong macro in the entry. It uses ON_NOTIFY_REFLECT() instead of ON_NOTIFY(). Since the HDN_ITEMCLICK is a notification from the header control to the list view control, it is a direct notification and not a reflected one.
    ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
    ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
 Note that we specify the same function for both the notification. Actually the program will receive one or the other and not both. What notification it receives will depend on the OS. The list view control on Windows 95 will send the ANSI version and the control on NT will send the UNICODE version.

Also, note that the second argument is zero. This value filters for the id of the control and we know that header control id is zero.

Step 4: Write the OnHeaderClicked() function

Heres where you decide what to do when the user clicks on a column header. The expected behaviour is to sort the list based on the values of the items in that column. In this function we have used the SortTextItems() function developed in a previous section. If any of the columns displays numeric or date values, then you would have to provide custom sorting for them.
 
void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult) 
{
        HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;

        if( phdn->iButton == 0 )
        {
                // User clicked on header using left mouse button
                if( phdn->iItem == nSortedCol )
                        bSortAscending = !bSortAscending;
                else
                        bSortAscending = TRUE;

                nSortedCol = phdn->iItem;
                SortTextItems( nSortedCol, bSortAscending );

        }
        *pResult = 0;
}
 



Comments

  • hnCDi MgW YDrf

    Posted by xiFZfhMHBG on 11/15/2012 02:31pm

    soma drug can i buy soma online - soma in urine drug screen

    Reply
  • The HDN_ITEMCLICK is not sent to the CMyListCtrl, why?

    Posted by cwgk_zc on 07/02/2006 03:45pm

    I do it following the steps above. I derive a class CMListCtrl from CListCtrl and then go as the steps. At last, I declare a variable CMyListCtrl m_list which is from resource. I insert three columns but when I click the headers, nothing happened. Can anyone tell me the reason? If send me the source code, this is very good.

    • It's sent to the parent (us. a dialog) instead

      Posted by Mr. X on 10/03/2007 11:36am

      The notification is sent to the parent - usually a dialog. You'll need to read up on the reflection mechanism (the MFC one, not the .NET one).

      Reply
    Reply
  • SortTextItems?

    Posted by mathieu1975 on 05/01/2006 01:46pm

    What is the SortTextItems doing? how do you sort the list? (manually? do a predefined method exist already?)

    • SortTextItems

      Posted by Mr. X on 10/04/2007 08:41am

      I just call my method RefreshList(), which I use in several places.  It does the following:
      1. creates a Clist of any selected items
      2. Clears the CListCtrl
      3. Requests & populates list data afresh
      4. Uses the CList from 1. to restore the selected items
      5. Calls my method - SortList()
      
      SortList() is just a switch which sets a function pointer to the appropriate compare-function to sort based on the selected column.  It then calls CListCtrl::SortItems - the CListCtrl's built-in sort method:
      
      void CMyDlg::SortList()
      {
      	PFNLVCOMPARE pfnCompare = NULL;	// Pointer to compare function
      	switch( m_nSortedCol )
      	{
      	case COLUMN_PROMPT_ID:		// Sort by ID
      		pfnCompare = CMyDlg::CompareIds;
      		break;
      
      	case COLUMN_PROMPT_NAME:	// Sort by file name
      		pfnCompare = CMyDlg::CompareNames;
      		break;
      
      	case COLUMN_PROMPT_TIME:	// Sort by date-time
      	default:
      		pfnCompare = CMyDlg::CompareTimes;
      		break;
      	}
      	m_ctrListFailedPrompts.SortItems( pfnCompare, (LPARAM)this );
      }

      Reply
    Reply
  • Nice and Simple.Great!!!

    Posted by Legacy on 12/12/2003 12:00am

    Originally posted by: Danushka Menikkumbura

    This helped me a lot.Nice work.Thanks a lot.

    Reply
  • It worked! Thank you!

    Posted by Legacy on 06/04/2003 12:00am

    Originally posted by: zhangyi

    int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
    
    

    CListSort::CListSort()
    {m_fAsc=TRUE;}

    CListSort::~CListSort()
    {
    }


    BEGIN_MESSAGE_MAP(CListSort, CListCtrl)
    //{{AFX_MSG_MAP(CListSort)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
    ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
    ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)

    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CListSort message handlers
    void CListSort::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
    {
    HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
    if( phdn->iButton == 0 )
    {
    //设置排序方式
    if( phdn->iItem == m_nSortedCol )
    m_fAsc = !m_fAsc;
    else
    m_fAsc = TRUE;
    //设置排序的列
    m_nSortedCol = phdn->iItem;
    //开始排序
    SortItems( ListCompare, (DWORD)this );
    }
    }

    /*
    typedef struct tagNMHEADER{
    NMHDR hdr;
    int iItem;
    int iButton;
    HDITEM FAR* pItem;}
    NMHEADER, FAR* LPNMHEADER;
    Members
    hdr
    NMHDR structure that contains information about the notification message.
    iItem
    Zero-based index of the header item that is the focus of the notification message.
    iButton
    Index of the mouse button used to generate the notification message. It is one of the following values:
    */
    int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
    //通过传递的参数来得到CSortList对象指针
    CListSort* pV=(CListSort*)lParamSort;
    //通过ItemData来确定数据
    DEMO_DATA* pInfo1=strAllData+lParam1;
    DEMO_DATA* pInfo2=strAllData+lParam2;
    CString szComp1,szComp2;
    int iCompRes;
    switch(pV->m_nSortedCol)
    {
    case(0):
    //以第一列为根据排序
    szComp1=pInfo1->szName;
    szComp2=pInfo2->szName;
    iCompRes=szComp1.Compare(szComp2);
    break;
    case(1):
    //以第二列为根据排序
    if(pInfo1->iAge == pInfo2->iAge)iCompRes = 0;
    else
    iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
    break;
    default:
    ASSERT(0);
    break;
    }
    //根据当前的排序方式进行调整
    if(pV->m_fAsc)
    return iCompRes;
    else
    return iCompRes*-1;
    }

    Reply
  • Thanx for the Info....very helpful

    Posted by Legacy on 05/14/2003 12:00am

    Originally posted by: Vikas Hegde


    Thank you Zafir...The callback function gave me problems....This saved a lot of my time.A very useful aricle.

    Reply
  • Anyone got a work around for this to work with Integer columns

    Posted by Legacy on 04/25/2003 12:00am

    Originally posted by: LizardKing

    This works great for String or Character based columns however numeric based columns get sorted incorrectly ( I know that this was pointed out in article) - Just wondering has anyone modified it to work on Integer based columns and if so , could they share the knowledge :)

    Cheers

    LK--<

    Reply
  • Thanks a lot!

    Posted by Legacy on 04/10/2003 12:00am

    Originally posted by: Ligh56t

    It's a good idea to make a message entry by myself.
    Thank you to let me know that
    Since the HDN_ITEMCLICK is a notification from the header control to the list view control, it is a direct notification and not a reflected one.

    Reply
  • dang

    Posted by Legacy on 10/09/2002 12:00am

    Originally posted by: amit gupta

    its very good but we want complete FAQ in a proper sequence

    Reply
  • It Worked

    Posted by Legacy on 07/29/2002 12:00am

    Originally posted by: Sheethal Shneoy

    Thanks Zafirji,Works absolutel fine.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

  • Application and data integration doesn't have to be slow and expensive. Learn how cloud-based integration platforms dramatically speed results and lower costs in this white paper by Bloor Research.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds