Получить положение объекта в списке в Delphi?

Мне было интересно, как вы получаете положение определенного объекта в списке, который создается. Допустим, это похоже на графический список, где вы можете нажимать на объекты. Допустим, вы щелкаете правой кнопкой мыши по объекту и нажимаете "Обновить", как мне получить позицию этого объекта, чтобы после обновления всего списка (по какой-то причине обновляется с помощью чистого списка) я возвращался к той же позиции в списке? Это если список имеет длину, скажем, 1000 объектов, что затрудняет попытку прокрутки вниз до той же позиции после обновления.

Код использует Tobject, но могу ли я сделать что-то вроде position:=integer(TObject."Pointerinfo???"); И после этого, когда программа обновляется, например, установить позицию представления для указателя, например currentview (указатель) или что-то в этом роде?

На самом деле это не обязательно должен быть один и тот же объект, но тот же "вид" списка будет еще лучше.

заранее спасибо

2 ответа

Решение

Поэтому я думаю, что с помощью, которую я получил, я ответил на свой вопрос. Что я сделал, так это написал что-то, что заняло x и y позиции списка, и позже, после того, как я сделал обновление с помощью clearlist, я использовал функцию прокрутки, чтобы вернуться к той же функции. Моя программа выглядит примерно так.

procedure Refresh(Sender: TObject);
var
  horzpos:integer;
  vertpos:integer;
begin
    horzpos:=ListView1.ViewOrigin.X;
    vertpos:=ListView1.ViewOrigin.Y;
    RefreshListView(ListView1); //A function that refreshes the list and clears it
    ListView1.Scroll(horzpos, vertpos);
 end;

Возможно, мне следовало бы заявить ранее, что это был тип списка, и что я хотел снова вернуться на ту же позицию после "чистого списка".

Спасибо за помощь, это сообщество рулит!

Если при обновлении вы снова получите тот же список и в том же порядке, не беспокойтесь об обнаружении чего-либо об объекте. Просто сохраните список элементов управления ItemIndex свойство, которое указывает текущий выбранный элемент.

Если при обновлении может появиться другой список, то нужный объект может оказаться не в том же положении, поэтому просто запомните ItemIndex не будет достаточно В этом случае вам нужно будет найти новую позицию объекта. Как это сделать, зависит от возможностей элемента управления списком и от того, как он предоставляет объекты, связанные с каждой позицией. Если у тебя есть TListBox, например, тогда Items собственность TStrings объект, и вы можете проверить каждое значение Objects массив, пока вы не найдете нужный объект. Сохраните значение ссылки на объект, а затем найдите его. Что-то вроде этого:

procedure Refresh;
var
  CurrentSelection: TObject;
  ObjectPosition: Integer;
  i: Integer;
begin
  if List.ItemIndex >= 0 then
    CurrentSelection := List.Strings.Objects[List.ItemIndex]
  else
    CurrentSelection = nil;
  RefreshList;
  ObjectPosition := -1;
  if Assigned(CurrentSelection) then begin
    for i := 0 to Pred(List.Count) do begin
      if List.Strings.Objects[i] = CurrentSelection then begin
        ObjectPosition := i;
        break;
      end;
    end;
  end;
  if ObjectPosition = -1 then
    // Object isn't in refreshed list
  else
    // It is.
end;

Последняя возможность заключается в том, что при обновлении вообще не сохраняются одни и те же объекты. Все предыдущие объекты уничтожаются, и создается новый список объектов. В этом случае вам придется запомнить некоторые идентифицирующие характеристики исходного объекта, чтобы вы могли найти новый объект, представляющий то же самое. Что-то вроде этого:

var
  CurrentObject, Person: TPerson;
  CurrentName: string;
  i, ObjectPosition: Integer;
begin
  if List.ItemIndex >= 0 then begin
    CurrentObject := List.Strings.Objects[List.ItemIndex] as TPerson;
    CurrentName := CurrentObject.Name;
  end else
    CurrentName = '';
  RefreshList;
  ObjectPosition := -1;
  if CurrentName <> '' then begin
    for i := 0 to Pred(List.Count) do begin
      Person := List.Strings.Objects[i] as TPerson;
      if Person.Name = CurrentName then begin
        ObjectPosition := i;
        break;
      end;
    end;
  end;
  if ObjectPosition = -1 then
    // Object isn't in refreshed list
  else
    // It is.
end;

Во всех этих случаях вы должны понимать, что позиция объекта в списке на самом деле не является свойством объекта. Скорее, это свойство списка, поэтому список играет такую ​​большую роль, как объект во всем этом коде. На самом деле нет никакой "указательной информации", которую можно получить от объекта, потому что объект, как правило, даже не подозревает, что находится даже в списке, поэтому он, конечно, не будет знать свою позицию относительно всех других элементов в списке.

После того, как вы определили положение объекта в списке, вам нужно прокрутить его в поле зрения. За TListBoxпростой способ установить его TopIndex имущество:

List.TopIndex := ObjectPosition;

И, наконец, если вы вообще не заботитесь о текущем объекте, а просто хотите восстановить текущую позицию прокрутки, тогда это еще проще:

procedure Refresh;
var
  CurrentPosition: Integer;
begin
  CurrentPosition := List.TopIndex;
  RefreshList;
  List.TopIndex := CurrentPosition;
end;
Другие вопросы по тегам