如何重建 TListView 但保留滚动信息?



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

我试过这个:

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年了。也许我们可以再试一次。

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

实际上,无需重建列表视图即可解决原始问题。这是 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;

最新更新