TListView:在运行时添加现有列之间的新列后,子项顺序是什么?

4

如果您在运行时在现有列之间添加新列,则子项索引不会像我预期的那样。

例如,在第二列和第三列之间添加新列后,列/子项如下所示:

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

但是我认为:

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

我需要能够根据某些条件动态更新子项的内容。因此,我希望可以依赖假设:具有Column.Index = X的列的子项在Item.SubItems[X-1]下。
您认为这是默认且预定的行为吗?如果是这样,您建议如何根据列更新子项。一种可能性是保存属于最近添加的列的子项索引。
注意:Columns.Tag属性已经在使用中。
我正在使用Delphi XE和XE2,但我需要与Delphi 7及更高版本兼容。

3
请将以下英文内容翻译成中文,仅返回翻译后的文本:由同一作者撰写的TListView:在运行时添加新列和子项的完全副本。 - Ken White
1
不是真的...也许你没有读到讨论...这只是一个小节选,不是其他主题中描述的错误的一部分。 - torno
3
我仍然建议使用虚拟列表视图。我相信这比尝试让列表视图存储所有内容更容易且更安全。在这里,间接引用是你的朋友。 - David Heffernan
2
看到你在这个问题和上一个问题中考虑的更改,我很难相信虚拟模式是更高风险的选项! - David Heffernan
1
我不明白“如果你添加一列,VCL如何失去列的顺序”和“如何确定重新排序的列下子项的位置”完全相同的含义。添加新列只是问题出现的方式,只要重新排列现有列,他就会遇到同样的问题。 - Sertac Akyuz
显示剩余4条评论
1个回答

3
你不需要保存索引位置,可以随时向列表视图控件本身询问列的原始位置:
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));


对于问题中的示例,ColumnOrder数组将包含(0, 1, 3, 2)。 如果我们想要更新新插入的列(从左边数第三列)的子项,则其原始位置为“3”。 代码示例:

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;

请注意,如果您正在添加列而不仅仅是重新排序现有列,则只有在其他问题中修复错误后才能正常工作(然而,如果没有这样做,提供列重新排序和列添加功能根本不可能)。
关于默认行为是否应该如此,假设您有一个列表视图,其中显示文件信息,具有“名称”、“大小”、“日期”等列。作为开发人员,您不应该担心用户可能放置“大小”列的位置,只需将信息放入“SubItems[0]”中即可。此外,如果用户拖动“名称”列,它会从项目降级为子项。
我认为可以合理地期望项目/子项遵循其各自的列。

这个非常好用!正是我想要的。非常感谢你。另外,移动/删除第0列在应用程序中不可能 :) - torno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接