Author: Jonas Bilinkevicius
Let's say we have a TPageControl with 15 pages, the design time PageIndex of each
page is 0 to 14 respectively. Now we want to change this order at runtime. The new
order is saved in an *.ini file, the values for the new order is stored in an array
of integer we will call MyOrder. Here is what the code would look like to change
the order:
var
i: Integer;
for i := 0 to PageControl1.PageCount - 1 do
PageControl1.Pages[i].PageIndex = MyOrder[i];
After executing this block of code the order of the pages is unchanged. Can you
tell my why this doesn't work?
Answer:
Solve 1:
Try this chunk of code. The key is that you set the 0th page index, then the 1rst,
then the 2nd and so on. Since you're doing them in order, they don't get screwed up
by later assignments.
1
2 procedure TForm1.ReorderBtnClick(Sender: TObject);
3 const
4 NewOrder: array[0..6] of Integer = (2, 0, 6, 1, 5, 3, 4);
5 var
6 X: Integer;
7 OrigPages: array of TTabSheet;
8 begin
9 {Keep an ordered list of tab sheets}
10 SetLength(OrigPages, 7);
11 for X := 0 to 6 do
12 OrigPages[X] := PageControl.Pages[X];
13 {Reorder tab sheets}
14 for X := 0 to 6 do
15 OrigPages[NewOrder[X]].PageIndex := X;
16 {Release ordered list of tab sheets}
17 OrigPages := nil;
18 end;
Solve 2:
This won't make order of the pages unchanged, but it won't give you the order you
expect either. Remember that while you are re-ordering the pagecontrol, the
pagecontrol also reorders itself. For example, you have a pagecontrol with 5 tabs,
labelled One, Two, Three, Four and Five. If you try to reorder so that these pages
move to the positions 3, 5, 1, 4, 2 respectively, then the order your code will put
them in will be Four, Three, Two, One, Five because of the way they get reordered
by the pagecontrol while you are moving them around.
Now, the really cool thing, and what seems to be happening to you, is that if you
apply the exact same reordering (using your algorithm) as first used, the tabs will
go back to the positions that they started from! Step through your code, and I'm
sure your reordering routine will be called twice. To reorder them successfully,
you would simply use a search and position algorithm, working from the last tab
position back to the first to get around the pagecontrol's own re-ordering. I'm not
sure from your post whether your array of positions is "for this position, this is
the page that goes here" or "for this page, this is the position it should be in",
so here is how to re-order your pagecontrol. We'll use the Tag property to let the
page remember where it should be. Use only *one* of the first two commented
for-loops, depending on your data structure.
19 { ... }
20 var
21 i, j: Integer;
22 begin
23 {Use this loop if the following describes your array:
24 "For this position (index), this is the page that goes here (contents)"
25 (that is, the contents of the array is the current pageindex, and the array
26 index is the new pageindex for that page)}
27
28 for i := 0 to PageControl1.PageCount - 1 do
29 PageControl1.Pages[MyOrder[i]].Tag := i;
30
31 {OR use this loop if the following describes your array:
32 "For this page (index), this is the position it should be in (contents)"
33 (That is, the array index corresponds to the current pageindex, and the contents
34 of the array is the new pageindex that page should have)}
35
36 for i := 0 to PageControl1.PageCount - 1 do
37 PageControl1.Pages[i].Tag := MyOrder[i];
38
39 {Then simply reorder the pagecontrol}
40 for i := PageControl1.PageCount - 1 downto 0 do
41 for j := 0 to i do
42 if PageControl1.Pages[j].Tag = i then
43 begin
44 PageControl1.Pages[j].PageIndex := i;
45 Break;
46 end;
47 end;
One of the two will work for you.
Solve 3:
The correct method to disconnect tabsheets and reconnect them:
48 { ... }
49 var
50 I: Integer;
51 L: TList;
52 begin
53 L := TList.Create;
54 try
55 {This just disconnects - you should replace this with your code to disconnect
56 them in the order you want to reconnect them}
57 for I := PageControl1.PageCount - 1 downto 0 do
58 begin
59 L.Add(PageControl1.Pages[I]);
60 PageControl1.Pages[I].PageControl := nil;
61 end;
62 {Reconnect...}
63 for I := 0 to L.Count - 1 do
64 TTabSheet(L[I]).PageControl := PageControl1;
65 finally
66 L.Free;
67 end;
68 end;
|