Как восстановить TListView, но сохранить информацию прокрутки? - PullRequest
0 голосов
/ 24 мая 2018

В TListView есть ошибка: когда вы находитесь в режиме vsReport с установленным GroupView и пытаетесь вставить элемент, он отображается последним в группе, а не там, где вы вставили.Проблема обсуждается здесь .Есть несколько ответов, но ни один из них не работает.Поэтому я думаю, что единственное решение - перестраивать весь список каждый раз, когда вы вставляете элемент.Это не просто, но я думаю, что смогу это сделать.Но есть большая проблема.Если окно прокрутки находится в середине списка, и я перестраиваю список, оно возвращает меня к началу.Можно как-то сохранить информацию прокрутки?

Я пробовал это:

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 голосов
/ 25 мая 2018

Как переместить вставленные элементы в правильную позицию?

На самом деле нет необходимости перестроить представление списка , чтобы обойти исходная проблема.Это проблема элемента управления представлением списка в Windows (его можно воспроизвести даже при вставке элементов в виде необработанного API, например, с помощью сообщения LVM_INSERTITEM ).

К счастью, объекты элементов представления списка 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;
...