Get position of object in a list in Delphi?
I was wondering how you get a position of a certain object in a list that is created. Lets say it is like a graphical list where you can click on objects. Lets say you right click on a object and click "Refresh", how do I get the position of that object so that after the whole list is refreshed (refreshes with a clearlist for some reason) i go back to the same position in the list? This is if the list is say 1000 objects long which makes it bothersome to try and scroll down to the same position after the refresh.
The code uses Tobject but can i do something like position:=integer(TObject."pointerinfo???"); And after that when the program refreshes like set the position of the view 开发者_开发技巧to the pointer like currentview(pointer) or something like that?
Actually it doesn't have to be the same object, but the same "view" of the list would be even better.
Thanks in advance
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;
So I think with the help I got I answered my own question. What I did was write something that took the x and y position of the listview and later after I did the refresh with a clearlist, I used the scroll function to get back to the same function. My program looks something like this.
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;
Maybe I should've stated earlier that it was a listview type and that I wanted to get back to the same position again after the "clearlist".
Thanks for all the help, this community rocks!
精彩评论