[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 282
  • Last Modified:

Data-aware Page control with 1 page per record?

Is there a data-aware component (preferably JVCL or similar) where I can have like a PageControl and have 1 page or tab per record?
So if my table has 5 records then there will be 5 pages?
Each page will then have some DBEdits and similar controls all laid out .
Of course these Data-Controls on the page will actually only be laid out on ONE page. Know what I mean?
0
rfwoolf
Asked:
rfwoolf
  • 4
  • 3
1 Solution
 
TheRealLokiSenior DeveloperCommented:
it sounds to me like you don't really need the PageControl at all.
You just want the "tabs" so the user can press them and go to the appropriate record.
you could put the data aware controls in 1 panel and just dynamically create some buttons.
or, if you really wanted, you could use a TPageControl, but set its' height to 25 and use the OnChange event to change to the appropriate record
0
 
rfwoolfAuthor Commented:
Yes and then I have to populate the tabs on teh PageControl because they won't be data-aware?
I suppose I could do that but I was hoping for something data aware and fluid.
I have played with the DBCtrlGrid but it doesn't have tabs.
0
 
TheRealLokiSenior DeveloperCommented:
no, you fake the pagecontrol, and use a panel below it,. you just use the "tabs" on the page control because it's easier

here's a quick demo I wrote up for you to show you what I mean.

unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, ExtCtrls, ImgList, ToolWin, DBCGrids, DBCtrls, Grids, DBGrids,
  Db, DBTables, contnrs, StdCtrls;
// written by }-=Loki=-{ June 2008 lokiwashere@yahoo.co.nz
type
  TTabKeyFields = class(TObject)
  public
    values: variant;
    constructor Create(Values_: variant);
  end;
 
type
  TForm1 = class(TForm)
    DataSource1: TDataSource;
    Table1: TTable;
    pMain: TPanel;
    PageControl1: TPageControl;
    bOpenCloseTable: TButton;
    DBText1: TDBText;
    DBText2: TDBText;
    DBImage1: TDBImage;
    Table1SpeciesNo: TFloatField;
    Table1Category: TStringField;
    Table1Common_Name: TStringField;
    Table1SpeciesName: TStringField;
    Table1Lengthcm: TFloatField;
    Table1Length_In: TFloatField;
    Table1Notes: TMemoField;
    Table1Graphic: TGraphicField;
    procedure bOpenCloseTableClick(Sender: TObject);
    procedure Table1BeforeOpen_or_AfterClose(DataSet: TDataSet);
    procedure Table1AfterOpen(DataSet: TDataSet);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    TabLinks: TObjectList;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.DFM}
 
{ TTabKeyFields }
 
constructor TTabKeyFields.Create(Values_: variant);
begin
  inherited Create;
  self.Values := values_;
end;
 
{ TForm1 }
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  TabLinks := TObjectList.Create;
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  TabLinks.Clear;
  TabLinks.Free;
end;
 
procedure TForm1.bOpenCloseTableClick(Sender: TObject);
begin
  Table1.Active := not Table1.Active;
end;
 
procedure TForm1.Table1BeforeOpen_or_AfterClose(DataSet: TDataSet);
var
  i: integer;
begin
  for i := pred(PageControl1.PageCount) downto 0 do
    PageControl1.Pages[i].Destroy;
  TabLinks.Clear;
end;
 
procedure TForm1.Table1AfterOpen(DataSet: TDataSet);
var
  newtabsheet: TTabSheet;
  newkeyfieldsobject: TTabKeyFields;
  i: integer;
begin
  TabLinks.Clear;
  for i := pred(PageControl1.PageCount) downto 0 do
    PageControl1.Pages[i].Destroy;
  Table1.DisableControls;
  try
    while not Table1.EOF do
    begin
      // we have 3 key fields in this demo - change this for your own purposes
      newkeyfieldsobject := TTabKeyFields.Create(VarArrayOf([Table1.Fields[0].AsVariant, Table1.Fields[1].AsVariant, Table1.Fields[2].AsVariant]) );
      TabLinks.Add(newkeyfieldsobject);
      newtabsheet := TTabSheet.Create(PageControl1);
      newtabsheet.Caption := Table1.Fields[1].AsString;
      newtabsheet.PageControl := PageControl1;
      newtabsheet.Tag := integer(newkeyfieldsobject);
      Table1.Next;
    end;
    Table1.First;
  finally
    Table1.EnableControls;
  end;
end;
 
procedure TForm1.PageControl1Change(Sender: TObject);
begin
  if (not assigned(PageControl1.ActivePage)) then exit;
  Table1.Locate(Table1.Fields[0].FieldName + ';' + Table1.Fields[1].FieldName +';' + Table1.Fields[2].FieldName,
    TTabKeyFields(PageControl1.ActivePage.Tag).values, []);
end;
 
end.
 
*****************
**** FORM FOLLOWS
*****************
 
object Form1: TForm1
  Left = 249
  Top = 107
  Width = 490
  Height = 335
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object pMain: TPanel
    Left = 8
    Top = 8
    Width = 445
    Height = 257
    Caption = 'pMain'
    TabOrder = 0
    object DBText1: TDBText
      Left = 32
      Top = 36
      Width = 42
      Height = 13
      AutoSize = True
      DataField = 'Category'
      DataSource = DataSource1
    end
    object DBText2: TDBText
      Left = 32
      Top = 60
      Width = 42
      Height = 13
      AutoSize = True
      DataField = 'Common_Name'
      DataSource = DataSource1
    end
    object PageControl1: TPageControl
      Left = 1
      Top = 1
      Width = 443
      Height = 25
      Align = alTop
      TabOrder = 0
      OnChange = PageControl1Change
    end
    object DBImage1: TDBImage
      Left = 52
      Top = 76
      Width = 265
      Height = 157
      DataField = 'Graphic'
      DataSource = DataSource1
      TabOrder = 1
    end
  end
  object bOpenCloseTable: TButton
    Left = 8
    Top = 272
    Width = 105
    Height = 25
    Caption = 'bOpenCloseTable'
    TabOrder = 1
    OnClick = bOpenCloseTableClick
  end
  object DataSource1: TDataSource
    DataSet = Table1
    Left = 232
    Top = 160
  end
  object Table1: TTable
    BeforeOpen = Table1BeforeOpen_or_AfterClose
    AfterOpen = Table1AfterOpen
    AfterClose = Table1BeforeOpen_or_AfterClose
    DatabaseName = 'DBDEMOS'
    TableName = 'biolife.db'
    Left = 196
    Top = 160
    object Table1SpeciesNo: TFloatField
      FieldName = 'Species No'
    end
    object Table1Category: TStringField
      FieldName = 'Category'
      Size = 15
    end
    object Table1Common_Name: TStringField
      FieldName = 'Common_Name'
      Size = 30
    end
    object Table1SpeciesName: TStringField
      FieldName = 'Species Name'
      Size = 40
    end
    object Table1Lengthcm: TFloatField
      FieldName = 'Length (cm)'
    end
    object Table1Length_In: TFloatField
      FieldName = 'Length_In'
    end
    object Table1Notes: TMemoField
      FieldName = 'Notes'
      BlobType = ftMemo
      Size = 50
    end
    object Table1Graphic: TGraphicField
      FieldName = 'Graphic'
      BlobType = ftGraphic
    end
  end
end

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
rfwoolfAuthor Commented:
Hmm.. thanks for that. It looks good. There are a few things that throw me out which means I would probably rewrite the whole thing...
[1] You 'used' contnrs which I don't know what that is and why you need it,
[2] I was playing with a PageControl and I couldn't seem to add any 'pages' in it using code - I can do this with TTabControls  by saying  tabcontrol1.Tabs.Insert( - so I would probably replace the PageControl with a TabControl. I think you create TTabsheets and then insert them O.o

So I would probably use a Tabcontrol and simply say
Table1.begin
While Table1.eof = false do
begin
  TabControl1.Tabs.Insert(Table1.FieldByName('Name').AsString);
  Table1.next;
end;

Of course, because the whole thing is not data-aware, if you delete a record (Table1.Delete) then you have to reprocess the Tabs. I was hoping for something data-aware and therefore more fluid, but so far this is the best bet
0
 
TheRealLokiSenior DeveloperCommented:
>  [1] You 'used' contnrs which I don't know what that is and why you need it,
 contnrs is used for the TObjectList
 when an object is deleted from that list, it is also free'd
it just saves you doing this
while (mylist.count >0) do
begin
  mylist[0].free;
  mylist.delete(0);
end;

>   [2] I was playing with a PageControl and I couldn't seem to add any 'pages' in it using code - I can do this with TTabControls  by saying  tabcontrol1.Tabs.Insert( - so I would probably replace the PageControl >  with a TabControl. I think you create TTabsheets and then insert them O.o

yes, the way to add pages at runtime is create the page, then tell it what pagecontrol it belongs to
You can however, very easily "insert" it where you like just by setting its' "PageIndex"
eg.
Page.PageIndex := 0; // make this the first page

You can easily use a tabcontrol if you like. This was just a demo :-)

>  Of course, because the whole thing is not data-aware, if you delete a record (Table1.Delete) then you >  have to reprocess the Tabs
You can set an "OnDelete" event of the table/query that just does
PageControl1.ActivePage.Destroy;
likewise, if you wished to support "insering a new record" you would need to create a new tab.
and if the "key fields" change, you need to update the TTabKeyFields values for that tab
(as easy as using the table's OnPost event to do

TTabKeyFields(PageControl1.Activepage.Tag).VarArrayOf([Table1.Fields[0].AsVariant, Table1.Fields[1].AsVariant, Table1.Fields[2].AsVariant]);
again


I have never come across a user friendly/easily customizable control that does what you are asking. Otherwise i would have suggested it :-)
0
 
rfwoolfAuthor Commented:
Thanks
0
 
rfwoolfAuthor Commented:
Thanks for the great solution RealLoki. Hopefully the team at JVCL and work on something like this.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now