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

时间:2018-05-24 13:23:08

标签: listview delphi delphi-2009

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

1 个答案:

答案 0 :(得分:3)

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

实际上不需要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;