【问题标题】:How to rebuild a TListView but keep the scroll information?如何重建 TListView 但保留滚动信息?
【发布时间】:2018-05-24 13:23:08
【问题描述】:

TListView 中有一个错误:当您在vsReport 模式下设置GroupView 并尝试插入一个项目时,它会显示在组中的最后而不是您插入的位置。这个问题正在讨论here。有几个答案,但没有一个有效。所以,我认为唯一的解决方案是每次插入项目时重建整个列表。这并不简单,但我想我可以做到。但是有一个大问题。如果滚动窗口位于列表的中间并且我重建了列表,它会将我送回到开头。是否可以以某种方式保留滚动信息?

我试过了:

procedure TNutrientsForm.Button2Click(Sender: TObject);
var ix,iy:Integer;
begin
 ix:= NList.ViewOrigin.X;
 iy:= NList.ViewOrigin.Y;
 NList.Items.BeginUpdate;
 RefreshList;
 NList.Scroll(ix, iy);
 NList.Items.EndUpdate;
end;

...但在vsReport 模式下,您只能滚动行高的倍数,因此它无法准确定位我应该在的位置。

不管怎样,如果你对上面链接中的问题也有答案,你可以把它贴在那里,我会很高兴的。我为此工作了 3 天,但没有找到解决方案。这个问题已经 9 岁了。也许我们可以再试一次。

【问题讨论】:

  • thisthis 有帮助吗?
  • 乍一看我无法让它工作,但我会进一步研究它。我认为GroupView:=true 搞砸了一切。

标签: listview delphi delphi-2009


【解决方案1】:

如何将插入的项目移动到正确的位置?

实际上不需要rebuild list view 来解决the original issue。这是 Windows 列表视图控件的问题(例如,即使在使用 LVM_INSERTITEM 消息以原始 API 方式插入项目时,它也可以重现)。

幸运的是,Delphi 列表视图项对象持有正确的索引值(在控件中的预期位置),所以剩下的就是通过它们重新排序 Windows 控件中的项。这可以通过自定义排序来完成。例如,您可以编写这样的辅助方法:

type
  TListViewHelper = class helper for TListView
  public
    function FixItemsOrder: Boolean;
  end;

function FixComparer(lParam1, lParam2, lParamSort: LPARAM): Integer; stdcall;
begin
  Result := TListItem(lParam1).Index - TListItem(lParam2).Index;
end;

function TListViewHelper.FixItemsOrder: Boolean;
begin
  Result := Boolean(SendMessage(Handle, LVM_SORTITEMS, 0, LPARAM(@FixComparer)));
end;

并且每当您插入一个项目(或多个项目)时,调用这样的方法:

var
  ListItem: TListItem;
begin
  ListView1.Items.BeginUpdate;
  try
    ListItem := ListView1.Items.Insert(0);
    ListItem.Caption := 'Item 1';
    ListItem.GroupID := 0;

    ListItem := ListView1.Items.Insert(0);
    ListItem.Caption := 'Item 2';
    ListItem.GroupID := 0;

    ListItem := ListView1.Items.Insert(0);
    ListItem.Caption := 'Item 3';
    ListItem.GroupID := 0;

    ListView1.FixItemsOrder;
  finally
    ListView1.Items.EndUpdate;
  end;
end;

【讨论】:

  • 这太不可思议了!这不仅仅是一个修复,它是一件艺术品。至少对我来说。我从没想过这个bug可以这么容易修复。我在它上面工作了 3 天,没有任何运气。非常感谢你,维多利亚!
  • 不客气!好吧,也许微软有一天会解决这个问题:)实际上,在我写了第一个版本并在网上搜索后,我发现即使people from .NET最后也使用了项目排序。
  • 所以这是操作系统的错误,而不是 Delphi 的错误?如果有一天该错误会得到纠正,我的软件会受到影响吗?
  • 是的,这是操作系统控制问题。在不使用任何 Delphi 类的情况下,我尝试插入一个项目,并使用 LVM_INSERTITEM 消息填充组 ID,结果是相同的;该项目已添加到组中的最后一个位置。不,这个问题的修复不应该是这个解决方法的问题(你只会执行额外的排序而没有实际效果,因为所有项目都已经在正确的位置上)。
  • 重点是 Delphi 知道项目的正确索引(并将它们存储在 TListItem.Index 属性中)。只是操作系统列表视图控件插入忽略它们的项目。所以唯一的技巧是我们戳操作系统控件,要求根据 Delphi 存储的正确索引进行排序。因此,如果有一天 MS 修复了控件,索引将与 Delphi 匹配,并且实际上不会发生排序(将运行,但没有任何反应)。
猜你喜欢
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 2011-07-25
  • 2011-08-16
  • 1970-01-01
相关资源
最近更新 更多