Link to home
Start Free TrialLog in
Avatar of RickJ
RickJ

asked on

Attach to Datasource Dataset change

I have an application that has many Tdatasource components.
The individual datasource components can change dataset many times at runtime.
I need to execute some code whenever this happens.
I need to create a unit that somehow attaches to the datasource dataset change property. It will perform my custom
processing then continue on with the dataset change. A code example would be good.
Any help is much appreciated.
Avatar of ceoworks
ceoworks

Hi, When TDataSource's DataSet property changed, OnStateChange event triggers :

TForm1 = class(TForm)
private
    ..
    ..
public
  ..
  procedure DoOnStateChange(Sender: TObject);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DataSource1.OnStateChange := DoOnStateChange;
end;

procedure TForm1.DoOnStateChage(Sender: TObject);
begin
  Caption := Caption + 'State Changed !!';
end;

Kind Regards,

Oktay Sancak
When TDataSource's OnStateChange event triggers, our DoOnStateChange procedure is running. Because we assigned OnStateChange event to our DoOnStateChange procedure with this code :

procedure TForm1.FormCreate(Sender: TObject);
begin
  DataSource1.OnStateChange := DoOnStateChange;
end;

Cheers,

Oktay Sancak
Avatar of RickJ

ASKER

Thanks for the comment ceoworks.
The OnStateChange is triggered by many things.
I am only iinterested in the changing of datasets.
I need to know what the dataset was before it is changed and what it is being changed to.
I specifically want to attach to the dataset property change.
Any ideas??

Thanks,
Rick.
Here is the Delphi's help files about OnStateChange :

"During the course of a normal connection to a database, a dataset’s state changes frequently. For example, each time a user starts editing a field in a data-aware control the dataset’s State property is changed from dsBrowse to dsEdit if the State is not already dsEdit. An OnStateChange event handler can respond to changes in state by taking actions such as disabling or enabling menu items or buttons."

When the OnStateChange event triggers, you can learn the current state of DataSet with "State" property.

property State: TDataSetState;

"TDataSetState indicates the current operating mode of a dataset component."

For example if DataSource.State is dsInactive, it means that dataset is closed and its data is unavailable.

--- EXAMPLE UNIT ---

AdoTable1 and AdoTable2 is connected to AdoConnection1 but they have different "TableName"s.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls;

type
  TForm1 = class(TForm)
    DataSource1: TDataSource;
    ADOTable1: TADOTable;
    ADOTable2: TADOTable;
    ADOConnection1: TADOConnection;
    btnSetTable1: TButton;
    btnSetTable2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnSetTable1Click(Sender: TObject);
    procedure btnSetTable2Click(Sender: TObject);
  private
    procedure DoOnStateChange(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  StateChangeCount: integer;

implementation

{$R *.dfm}

procedure TForm1.DoOnStateChange(Sender: TObject);
begin
  Inc(StateChangeCount);
  Form1.Caption := 'DataSet State Changed ' + IntToStr(StateChangeCount) + ' times';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DataSource1.DataSet := ADOTable1;
  DataSource1.OnStateChange := DoOnStateChange;
end;

procedure TForm1.btnSetTable1Click(Sender: TObject);
begin
  DataSource1.DataSet := ADOTable1;
end;

procedure TForm1.btnSetTable2Click(Sender: TObject);
begin
  DataSource1.DataSet := ADOTable2;
end;

end.

Cheers,

Oktay Sancak
Avatar of RickJ

ASKER

Thanks again for your comments Oktay,
The onstatechange will let me know when the dataset is changed, but I need to do processing before it is changed.

My application has around 200 forms. All of these forms are opened from the one procedure.
I was thinking that I could maybe loop through the components on the form when it is created, finding all the tdatasource
components. When I find a tdatasource component I would like to redirect its dataset change property to a custom property change.
I hope this gives a better picture of what I am trying to achieve.
Do you think this is possible ??  Any more Ideas??
When i change the DataSet property in runtime like i did in my code, State is changing two times. First of all changing to dsInactive then to dsBrowse. When it change to dsInactive, old DataSet is closing then State is changing to dsBrowse and it means that new DataSet is ready to view. You can store the old value of DataSet property and then check it with State's dsBrowse property change.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls;

type
  TForm1 = class(TForm)
    DataSource1: TDataSource;
    ADOTable1: TADOTable;
    ADOTable2: TADOTable;
    ADOConnection1: TADOConnection;
    btnSetTable1: TButton;
    btnSetTable2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnSetTable1Click(Sender: TObject);
    procedure btnSetTable2Click(Sender: TObject);
  private
    procedure DoOnStateChange(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  StateChangeCount: integer;
  ExDataSet: TDataSet;

implementation

{$R *.dfm}

procedure TForm1.DoOnStateChange(Sender: TObject);
begin
  if (DataSource1.State = dsBrowse) and (DataSource1.DataSet <> ExDataSet) then
  begin
    ShowMessage('DataSet Changed');
    ExDataSet := DataSource1.DataSet;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DataSource1.DataSet := ADOTable1;
  ExDataSet := ADOTable1;
  DataSource1.OnStateChange := DoOnStateChange;
end;

procedure TForm1.btnSetTable1Click(Sender: TObject);
begin
  DataSource1.DataSet := ADOTable1;
end;

procedure TForm1.btnSetTable2Click(Sender: TObject);
begin
  DataSource1.DataSet := ADOTable2;
end;

end.
Avatar of RickJ

ASKER

Hello Oktay,
I need to do my processing when the old dataset is still actively connected to the datasource.
And then some more processing when the dataset has changed.

Thanks
Rick.
Hi Rick,

It looks like a hard work or i'm really sleepy :) I understand what you mean. You wants to become aware before the DataSet change. Ok i'll try.
TDataSource doesn't have a good way to do that. It looks like there isn't any way to do that before ex-dataset closed. I thought to create a new DataSource component with overriding TDataSource's SetDataSet procedure. With it we can be aware of the changes(before and after..) in DataSet property. But looks not possible because SetDataSet procedure is in the private section. TDataSet events not working too..
Avatar of RickJ

ASKER

That is exactly where I am at.
I have attempted what you were thinking and came up with the same result.
I am starting to wonder if it is possible?? My head is starting to hurt!!

Thanks for the help Oktay.
ASKER CERTIFIED SOLUTION
Avatar of ceoworks
ceoworks

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial