除了问题中报告的内容之外,还有更多内容(最后更多)。
这与您之前的问题有关。该问题涉及列表视图控件在添加列后移动列时丢失列和项/子项之间的映射。我提出了一个可能的解决方案,comctrls.pas
其中涉及FOrderTag
在移动列时保留 s 列。每当移动列时,VCL 都会从头开始构建“FOrderTag” - 不考虑列的当前位置。
然后发生的事情是,您提交错误报告,提交可能的修复作为解决方法,然后它会按原样签入。现在您发现的问题是,当我们保留FOrderTag
每一列,然后从中间删除一列时,我们会创建一个洞 - 它们不再是连续的(假设我们有带有各自顺序标签的第 0、1 和 2 列,删除第 1 列,现在我们有 2 列,订单标签为 0 和 2)。显然本机控件不喜欢这样。
再次修改 VCL,我们可以在移除列时移除任何可能的孔。当您调整/移动问题评论中提到的缺少标题的列时,下面似乎会处理缺少的标题和 AV。
destructor TListColumn.Destroy;
var
Columns: TListColumns;
i: Integer; //+
begin
Columns := TListColumns(Collection);
if TListColumns(Collection).Owner.HandleAllocated then
ListView_DeleteColumn(TListColumns(Collection).Owner.Handle, Index);
//{+
for i := 0 to Columns.Count - 1 do
if Columns[i].FOrderTag > FOrderTag then
Dec(Columns[i].FOrderTag);
//}
inherited Destroy;
Columns.UpdateCols;
end;
现在,如果我们回到问题中未报告的内容,如果您插入了一些子项,您会注意到它们保留了它们的位置,IOW 列和子项之间的映射丢失了。您的观点可能与我的观点不同,但我认为已删除列的子项应该会丢失。不幸的是,我无法找到实现这一目标的方法。
编辑:我想不出任何可以在 VCL 中轻松集成/修复的东西。没有什么能阻止您删除第一个插入的列。这一项对应items,如果我们删除items,所有子item也会被取出。VCL 中的当前实现是,当您删除列时,实际上不会删除任何项目数据。您可以通过在删除一列后添加一列来验证这一点,子项将神奇地出现在新列下。
无论如何,我可以建议您手动删除已删除列的子项。以下是删除列及其相应子项的实用程序示例:
procedure ListViewDeleteColumn(ListView: TListView; Col: Integer);
var
i: Integer;
ColumnOrder: array of Integer;
begin
SetLength(ColumnOrder, ListView.Columns.Count);
ListView_GetColumnOrderArray(
ListView.Handle, ListView.Columns.Count, PInteger(ColumnOrder));
Assert(ColumnOrder[Col] <> 0, 'column with items cannot be removed');
for i := 0 to ListView.Items.Count - 1 do
if Assigned(ListView.Items[i].SubItems) and
(ListView.Items[i].SubItems.Count >= Col) then
ListView.Items[i].SubItems.Delete(ColumnOrder[Col] - 1);
ListView.Columns.Delete(Col);
end;
如果您决定删除第一列,请决定您将如何处理项目/子项目并重建它们。