Если при обновлении вы снова получите тот же список и в том же порядке, не беспокойтесь об обнаружении чего-либо об объекте. Просто сохраните свойство 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;