If refreshing is going to give you the same list again, and in the same order, then don't bother discovering anything about the object. Just store the list control's ItemIndex
property, which indicates the currently selected item.
If refreshing might give you a different list, then the object you want might not be at the same position afterward, so just remembering ItemIndex
won't be enough. In that case, you'll need to find the new position of the object. How to do that depends on the capabilities of the list control and how it exposes the objects associated with each position. If you have a TListBox
, for example, then the Items
property is a TStrings
object, and you can inspect each value of the Objects
array until you find the object you want. Store the value of the object reference, and then search for that. Something like this:
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;
A final possibility is that refreshing doesn't actually keep the same objects at all. All the previous objects are destroyed, and a new list of objects is generated. In that case, you'll have to remember certain identifying characteristics of the original object so you can find the new object that represents the same thing. Something like this:
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;
In all these cases, you should realize that the object's position in the list is not actually a property of the object. Rather, it's a property of the list, which is why the list plays such a bigger role than the object in all that code. There isn't really any "pointerinfo" to get from the object because the object, in general, has no idea it's even in a list, so it certainly won't know its position relative to all the other items in the list.
Once you've determined the position of the object in the list, you need to scroll it into view. For TListBox
, a simple way is to set its TopIndex
property:
List.TopIndex := ObjectPosition;
And finally, if you don't actually care about the current object at all, but just want to restore the current scroll position, then that's even easier:
procedure Refresh;
var
CurrentPosition: Integer;
begin
CurrentPosition := List.TopIndex;
RefreshList;
List.TopIndex := CurrentPosition;
end;