【问题标题】:How to prevent listview from jumping to selected/focused row on item.count change?如何防止列表视图在 item.count 更改时跳转到选定/焦点行?
【发布时间】:2018-09-27 09:28:32
【问题描述】:

我有一个虚拟列表视图,我打算用它来显示一个相当大的日志文件中的内容。

每当添加或删除一行时,我在列表框中选择或聚焦(或两者)行,它会自动滚动回它,这很烦人。

当项目计数被修改时,感觉就像有东西在调用 MakeVisible(或做同样事情的东西)。

重现它的非常简化的示例:

procedure TForm1.FormCreate(Sender: TObject);
var
  Col: TListColumn;
begin
  ListView1.OwnerData := True;
  ListView1.ViewStyle := vsReport;
  ListView1.RowSelect := True;

  Col := ListView1.Columns.Add;
  Col.Caption := 'LineNum';
  Col.Alignment := taLeftJustify;
  Col.Width := 70;
end;
// listview onData event
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
  Item.Caption := IntToStr(Item.Index+1);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  ListView1.Items.Count := ListView1.Items.Count + 10;
end;

编辑:测试不同的 ViewStyles,这只发生在 vsReport 和 vsList

【问题讨论】:

  • 哪个 Delphi 版本? VCL 还是 FMX?
  • 可能 VCL 作为使用列表由 VCL.whatevers 组成,它是 10.2 tokyo

标签: listview delphi vcl delphi-10.2-tokyo


【解决方案1】:

问题在于TListItems.Count 属性设置器调用ListView_SetItemCountEx() 时没有LVSICF_NOSCROLL 标志:

当项目计数改变时,列表视图控件不会改变滚动位置。

procedure TListItems.SetCount(Value: Integer);
begin
  if Value <> 0 then
    ListView_SetItemCountEx(Handle, Value, LVSICF_NOINVALIDATEALL)
  else
    ListView_SetItemCountEx(Handle, Value, 0);
end;

这就是 ListView 在Count 更改时滚动的原因。您必须自己直接致电ListView_SetItemCountEx(),以便指定LVSICF_NOSCROLL 标志。

uses
  ..., CommCtrl;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  //ListView1.Items.Count := ListView1.Items.Count + 10;
  ListView_SetItemCountEx(ListView1.Handle, ListView1.Items.Count + 10, LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL);
end;

【讨论】:

  • 非常感谢,这完全解决了问题,我实际上已经在查看头文件,但没有找到标志。
猜你喜欢
  • 2014-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
相关资源
最近更新 更多