Positioned vs. non-positioned listview views

Occasionally, I'll see a question that betrays a lack of understanding of difference between the positioned and non-positioned listview views. The question usually goes along the lines of "I inserted an item with LVM_INSERTITEM but it went to the end of the list instead of in the location I inserted it."

To understand what is going on, you need to know that some listview views are "positioned" and others are "non-positioned".

"(Large) icon view", "small icon view", and "tile view" are positioned views. Each item carries its own coordinates, which you can customize via LVM_SETITEMPOSITION. When a new item is inserted, it gets an item index based on the insertion point, but its physical location on the screen is the first available space not already occupied by another item. Existing items are not moved around to make room for the inserted item.

The other views, "list view" and "report (aka details) view", are non-positioned views. In these views, items do not get to choose their positions. Instead, the position of an item is determined by its item index. In non-positioned views, inserting or deleting an item will indeed cause all subsequent items to shift.

Now you can answer the question. Why did the item go to the end of the list instead of at the position the caller inserted it?

Comments (7)
  1. Mike Dunn says:

    The mistake I see most often is people using LVM_INSERTITEM to add text to columns 2 and beyond, instead of LVM_SETITEMTEXT. There’s a leaky abstraction there in that LVM_INSERTITEM inserts a whole row and you have to use some other message for the later columns.

    Thinking that you use LVM_INSERTITEM for those columns seems like a natural assumption since LVITEM has a iSubItem member.

  2. Raymond Chen says:

    Nothing leaky about it. The abstraction is maintained. There are items and subitems.

    What would it mean to "insert a subitem"? Would all the subsequent subitems shift down by one? What happens to the last subitem that doesn’t have a column?

  3. Mike Dunn says:

    I think it’s leaky because it’s exposing the fact that an "item" means "a whole row". You first use LVM_INSERTITEM which sets the text in subitem 0. LVM_INSERTITEM also inserts an empty string in all subsequent subitems, but from just looking at the list you wouldn’t know this.

    So Joe Newbie Programmer thinks, "ok now I need to put a string in subitem 1, so I’ll use LVM_INSERTITEM again and set LVITEM::iSubItem to 1". Of course, this is wrong. He has to figure out (or have someone explain) that there’s a different message he has to use for subitems 1 to n.

    It’s one of those things that, once you learn the right way, you don’t forget it. But the first time is always a bit weird because until you start coding with a list control, you don’t know that subitem 0 is different from the others.

  4. Raymond Chen says:

    That’s not a leaky abstraction. It’s an abstraction that may be have been poorly-designed, but it’s still an abstraction.

    Item = unit of selection (includes icon, text, state, supplementary info)

    Subitem 0 = item text

    Subitem >0 = supplementary info

    The confusing bit is that subitem=0 means "the item’s text".

    There is no implementation "leaking out" – you might think that the implementation is leaking out – that listview internally has a list of subitems and subitem 0 happens to be the item text – but in fact that’s not how listview organizes the items internally.

    If you still claim that something is leaking out, the thing that is "leaking" isn’t even the implementation.

  5. Mike Dunn says:

    OK, we agree that there’s a hurdle there for newbies, but we disagree on what to call it. ;)

  6. When is ListView going to have editable subitems? This is something that I have wanted for a long time.

  7. Raymond Chen says:

    Remember, folks, this blog is about history not about the future.

Comments are closed.

Skip to main content