Получить положение объекта в списке в 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;