4

If you add a new column between existing columns during runtime, the subitem indices are not like I'ld assume.

e.g. after adding a new column between the second and third column the columns/subitems look like this:

colums[0] |  colums[1]   |  (new) columns[2] |  columns[3]
caption   |  subitems[0] |  subitems[2]      |  subitems[1]

but i would assume:

colums[0] |  colums[1]   |  (new) columns[2] |  columns[3]
caption   |  subitems[0] |  subitems[1]      |  subitem[2]

I need to be able to dynamically update the subitem's content under some conditions. That's why I would like to rely on the assumption, that the subitem for a column with Column.Index = X is at Item.SubItems[X-1].

Do you think this is a default and designated behavior? If so, what would you suggest for updating the subitems according to the columns. A possibility might be saving the subitem index that belongs to the recently added columns.

Note: The Columns.Tag-property is already in use.

I`m using Delphi XE and XE2, but I need to be compatible with Delphi 7 and higher.

Ken White
  • 123,280
  • 14
  • 225
  • 444
torno
  • 466
  • 12
  • 25
  • 3
    exact duplicate of [TListView: adding new column and subitems during runtime](http://stackoverflow.com/questions/8258386/tlistview-adding-new-column-and-subitems-during-runtime) by same author. – Ken White Nov 30 '11 at 14:40
  • 1
    not really... maybe you did not read the discussion... this is just a small excerpt and was not part of the described bug in the other thread. – torno Nov 30 '11 at 14:43
  • Actually, I read it quite carefully, both as it was ongoing and just now before linking to it. – Ken White Nov 30 '11 at 14:50
  • ok, sorry, you might be partially right. the other thread contains two questions/issues - what I did not know when i opened it. but i`ll edit the other thread so it just contains the answered part. – torno Nov 30 '11 at 14:51
  • 3
    I'd still just do this with a virtual list view. I still believe that will be easier and safer than trying to get the list view to store everything. Indirection is your friend here. – David Heffernan Nov 30 '11 at 15:13
  • using virtual mode is considered for a later version because using it would result in large effort to adjust the code. but i hope to find a easyier solution for a bugfix version. – torno Nov 30 '11 at 15:20
  • 2
    Looking at the changes you are contemplating in this question and the last, I find it hard to believe that virtual mode is the higher risk option! – David Heffernan Nov 30 '11 at 15:52
  • you might be right, but I shouldn`t change such a basic part for a bugfix version. if I won't find a better solution in time, the releas has to be done without a proper fix and I will check virtual mode afterwards. – torno Nov 30 '11 at 16:14
  • 1
    I don't see how *"how the VCL looses the order of columns if you add a column"* is exactly the same as *"how you'll locate the position of a subitem under a re-ordered column"*. Adding a new column is just how the OP faced the problem, just shuffle existing columns and he'll have the same problem. – Sertac Akyuz Nov 30 '11 at 21:57

1 Answers1

3

You don't need to save index positions, you can always ask the list view control itself the columns' original position:

procedure TForm1.Button1Click(Sender: TObject);
var
  ColumnOrder: array of Integer;
begin
  SetLength(ColumnOrder, ListView1.Columns.Count);
  ListView_GetColumnOrderArray(ListView1.Handle, ListView1.Columns.Count,
                               PInteger(ColumnOrder));


For the example in the question, the ColumnOrder array will hold (0, 1, 3, 2). If we want to update the subitem of the newly inserted column (3rd column from left), then its original position is '3'. Code example:

var
  ColumnOrder: array of Integer;    
  SubIndex: Integer;
begin
  SetLength(ColumnOrder, ListView1.Columns.Count);
  ListView_GetColumnOrderArray(ListView1.Handle, ListView1.Columns.Count,
                               PInteger(ColumnOrder));

  SubIndex := ColumnOrder[2];    // We want to update 3rd column from left
                                 // (visually -> SubItems[1])

  // Test if the index is not 0, otherwise it holds an *item*,
  // not a subitem (the first column can change position too).
  if SubIndex > 0 then begin     
    Dec(SubIndex);               // VCL subitems are 0 based
    ListView1.Items[1].SubItems[SubIndex] := 'updated!';
  end;


Note that if you're adding columns and not just re-ordering existing ones, this will only work if you have a fix for the bug in the other question (then again if you don't, providing both column re-ordering and column adding functionality is not possible at all anyway).


Regarding if the default behavior is as it should be, suppose you have a list view which you're displaying file information having columns 'name', 'size', 'date'. As a developer you shouldn't be worrying about where a user might have put the 'size' column, just put the information to 'SubItems[0]'. Furhermore, what if the user drags the 'name' column, will it demote from being an item to a subitem.

I'd think it is only logical to expect that items/subitems would follow their respective columns..

Community
  • 1
  • 1
Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • this works very nice! exactly what I was looking for. thank you really much. and: moving/removing column 0 is not possible in the app :) – torno Dec 01 '11 at 12:53