隐藏空 space 在不可见的列表框项目后面

Hide empty space behind invisible list box items

我可以看到 other people have had this issue,建议的解决方案对我不起作用。

我有一个列表框,其中包含许多在设计时填充的静态项,而在 运行 时,一些列表框项的可见性发生了变化。但是,那些不可见的项目会在该项目所属的列表框中留下一个空的 space。建议将不可见项目高度设置为0,这显然对人们有用,但对我不起作用。

这是我为此编写的一个常用函数:

procedure FixHidden(AListBox: TListBox);
var
  X: Integer;
  I: TListBoxItem;
begin
  for X := 0 to AListBox.Count-1 do begin
    I:= AListBox.ItemByIndex(X);
    if I.Visible then
      I.Height:= AListBox.ItemHeight
    else
      I.Height:= 0;
  end;
end;

在单步执行代码时,我可以确认在 I.Height:= 0; 之后 Height 实际上是 0。但是,问题仍然存在,列表框中仍然有一个空白,好像列表框控件忽略了我设置的项目的高度。

如何使不可见的项目真正从列表框中隐藏起来,包括它后面的空 space,而不删除这些项目?我的应用程序有许多具有相同问题的不同列表框控件,因此一个全局解决方案将是理想的。

注意:这是使用 Windows 32 作为平台。

编辑

我又做了几次试验,发现了一些东西。在设计时,列表框项目 Height 属性 默认为父列表框的 ItemHeight 属性。如果我在设计时更改特定项目的 Height,它会立即恢复到原来的状态。所以问题就变成了......为什么每次我更改 Firemonkey 时都会恢复 TListBoxItem.Height

感谢 Tom 在评论中提供的一些故障排除帮助,我发现了问题所在以及解决方法。

问题的根源在于我的 TListBox 控件被赋予了 ItemHeight 的自定义值,尽管默认情况下它们具有 0。当 ItemHeight0 时,您可以设置单个项目的高度。但是,当 ItemHeight 为其他任何内容时,列表框控件会接管并强制将所有项目设置为该高度,而不管您为每个项目分配什么。

所以解决这个问题的步骤是:

  1. TListBox.ItemHeight 属性 设置回 0
  2. 将每个项目的 TListBoxItem.Height 属性 设置为所需的高度
  3. 修改我的程序以设置所需的高度而不是 TListBox.ItemHeight

程序现在看起来像这样:

procedure FixHidden(AListBox: TListBox; AHeight: Extended = 32.0);
var
  X: Integer;
  I: TListBoxItem;
begin
  for X := 0 to AListBox.Count-1 do begin
    I:= AListBox.ItemByIndex(X);
    if I.Visible then
      I.Height:= AHeight
    else
      I.Height:= 0;
  end;
end;

这仍然是对原始潜在问题的一个相当混乱的修复,但它确实解决了问题。

如果出于任何原因您希望能够拥有不同高度的列表项,您可以通过将所需高度存储在每个列表框项的 Tag 属性 中来实现(尽管TagNativeIntHeightExtended 所以准确性会丢失) ...

procedure FixHidden(AListBox: TListBox);
var
  X: Integer;
  I: TListBoxItem;
begin
  for X := 0 to AListBox.Count-1 do begin
    I:= AListBox.ItemByIndex(X);
    if I.Visible then
      I.Height:= I.Tag
    else
      I.Height:= 0;
  end;
end;