wxListCtrl: ID vs. Index Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
jpo234
In need of some credit
In need of some credit
Posts: 9
Joined: Tue Feb 25, 2020 11:34 am

wxListCtrl: ID vs. Index

Post by jpo234 » Thu Mar 26, 2020 6:11 pm

Hello all,
accessing items in a wxListCtrl happens with the help of a long value that is always named "item". Examples:

Code: Select all

wxUIntPtr wxListCtrl::GetItemData( long  item) const;
bool wxListCtrl::DeleteItem ( long  item);
Now my question:

Code: Select all

long wxListCtrl::InsertItem (wxListItem & info)
is documented as
Inserts an item, returning the index of the new item if successful, -1 otherwise.
I get an error, when the wxListItem doesn't have a valid ID assigned with wxListItem::SetId(). Does this mean that there is a difference between the ID value in wxListItem and the Index in the wxListCtrl?
Or in other words: Is it correct to loop over the items in a wxListCtrl like this (m_keylist points to a wxListCtrl):

Code: Select all

            for (unsigned long id = 0; id < m_keylist->GetItemCount(); id++) {
                result += m_keylist->IsItemChecked(id) ? 1 : 0;
            }
Thanks in advance
J.

jpo234
In need of some credit
In need of some credit
Posts: 9
Joined: Tue Feb 25, 2020 11:34 am

Re: wxListCtrl: ID vs. Index

Post by jpo234 » Mon Mar 30, 2020 8:19 am

I'd like to point out, that the examples on the Wiki page contradict each other on this topic.

The "Minimal example to get started" does this:

Code: Select all

        for (int n=0; n<item_amount; n++)
        {
            Item* curritem = getItem(n);
            
            wxListItem item;
            item.SetId(n);
            item.SetText( curritem->getName() );
            
            m_item_list->InsertItem( item );
            
            // set value in first column
            if (!curritem->isFoo())
            {
                m_item_list->SetItem(n, 0, wxT("Foo"));
            }
            else
            {
                m_item_list->SetItem(n, 0, wxT("Bar"));
            }
e.g. it uses the variable n as ID in item.SetId(n) and index or whatever in m_item_list->SetItem().

The example "Adding items in a multiple column list" does this:

Code: Select all

long itemIndex = WxListCtrl1->InsertItem(0, "1"); //want this for col. 1
WxListCtrl1->SetItem(itemIndex, 1, "18:00"); //want this for col. 2
WxListCtrl1->SetItem(itemIndex, 2, "17 18 56 48 29 13"); //col. 3
e.g. it uses the itemIndex returned from wxListCtrl::InsertItem() as if it's different from the ID value in wxListCtrl::InsertItem().

Reagrds
J.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2230
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxListCtrl: ID vs. Index

Post by PB » Mon Mar 30, 2020 9:21 am

I think you do not have to be concerned about this. I believe it is generally not possible for the wxListItem id (= 0-based position of the id in the list control) to be different from the actual item list index.

Of course, the returned index can still be different than the id when inserting an item. E.g., if one has an empty list and calls

Code: Select all

long idx = m_listView->InsertItem(20, "Blah");
at least on MSW the returned value will be the actual index of the inserted item (and so will be the item id of the newly inserted item, should you retrieive it), i.e. 0 and not (the impossible) 20.

jpo234
In need of some credit
In need of some credit
Posts: 9
Joined: Tue Feb 25, 2020 11:34 am

Re: wxListCtrl: ID vs. Index

Post by jpo234 » Mon Mar 30, 2020 11:26 am

PB wrote:
Mon Mar 30, 2020 9:21 am
I think you do not have to be concerned about this. I believe it is generally not possible for the wxListItem id (= 0-based position of the id in the list control) to be different from the actual item list index.

Of course, the returned index can still be different than the id when inserting an item. E.g., if one has an empty list and calls

Code: Select all

long idx = m_listView->InsertItem(20, "Blah");
at least on MSW the returned value will be the actual index of the inserted item (and so will be the item id of the newly inserted item, should you retrieive it), i.e. 0 and not (the impossible) 20.
Thank's for taking the time to think about this. What I'm wondering is an enhanced version of your example:

Code: Select all

wxListItem info;
info.SetId (20);
info.SetText ("Blah");
m_listView->InsertItem(info);
info.Clear ();
info.SetId (20);
m_listView->GetItem (info);
Do I get the information from the InsertItem call or do I try to access a non existing item (because the ID changed to 0)? Is the ID guaranteed to be the same as the index (and those does changes with the item's position in the list) or is the ID guaranteed to be constant (and those doesn't change with the position of the item in the list)? Right now I have written my code to not rely on the identity between index and id, but it's ugly because I'm tracking the ID ==> Index mapping manually. If there is a guarantee that ID == Index, I could get rid of this mapping.

Thanks
J.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2230
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxListCtrl: ID vs. Index

Post by PB » Mon Mar 30, 2020 11:57 am

jpo234 wrote:
Mon Mar 30, 2020 11:26 am
Thank's for taking the time to think about this. What I'm wondering is an enhanced version of your example:

Code: Select all

wxListItem info;
info.SetId (20);
info.SetText ("Blah");
m_listView->InsertItem(info);
info.Clear ();
info.SetId (20);
m_listView->GetItem (info);
(Based on my observation on MSW for a list with wxLC_LIST style, there can a be a bug/inconsistency on other platforms) Assuming the list has less than 20 items before executing the code above:
  • m_listView->InsertItem(info)" will return value equal to m_listView->GetCount().
  • m_listView->GetItem(info) will return false and hence info is invalid.
If the order of the items in your list never changes, I think it is safe to use index.

OTOH, I often keep the info in the user data in list controls (wxListCtrl, wxListBox, wxComboBox...), e.g. when the control is sorted. Imagine the control having an unchanging list of countries sorted by name. The order cannot be relied on e.g. when localization is involved, so one cannot rely on index or string value of the item...

But if you want just a numeric ID, why not use wxListCtrl::SetItemData(long, long)?

jpo234
In need of some credit
In need of some credit
Posts: 9
Joined: Tue Feb 25, 2020 11:34 am

Re: wxListCtrl: ID vs. Index

Post by jpo234 » Mon Mar 30, 2020 12:21 pm

PB wrote:
Mon Mar 30, 2020 11:57 am
But if you want just a numeric ID, why not use wxListCtrl::SetItemData(long, long)?
I was thinking about this very option. I think this is what I'm going to do. My lists aren't long, so a

Code: Select all

wxListCtrl::whatever(wxListCtrl::FindItem(-1, myid));
won't kill me.

Thanks
J.

Post Reply