BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problem with automatic switching of client dataset state dur

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Databases (dbExpress)
View previous topic :: View next topic  
Author Message
Enquiring Mind
Guest





PostPosted: Tue Apr 10, 2007 5:33 pm    Post subject: Problem with automatic switching of client dataset state dur Reply with quote



Hi,

I have a client dataset called cdsEmployee that contains data from the
EMPLOYEE table of the EMPLOYEE.GDB database. I have defined a form class
TFormEmployeeRecord that displays the fields of an individual record using
data-aware controls linked to cdsEmployee, but I have deleted the global
variable FormEmployeeRecord from the unit with the form's class, as I want
the form to be instantiated inside a procedure. I have included in the unit
2 global procedures called ShowEmployeeRecord and ShowNewEmployeeRecord
designed to be called from another form. These create an internal instance
of the TFormEmployeeRecord form, then show the form in modal mode. The
ShowNewEmployeeRecord is as follows:

procedure ShowNewEmployeeRecord;
var
FormEmployeeRecord: TFormEmployeeRecord;
begin
{if FormEmployeeRecord<>nil then
FreeAndNil(FormEmployeeRecord); }
FormEmployeeRecord:= TFormEmployeeRecord.Create(nil);
try
Datamodule1.cdsEmployee.DisableControls;
Datamodule1.cdsEmployee.Insert;
FormEmployeeRecord.ShowModal;
finally
FreeAndNil(FormEmployeeRecord);
end;
end;

The purpose of this procedure is to display an empty record in Insert mode.
However I have encountered the following problems:

1. The "if FormEmployeeRecord<>nil " statement (that is commented out ) does
not work as I would expect. Even though FormEmployeeRecord is declared as a
local variable of the procedure, and there is no global variable by the same
name, Delphi does not initialise the variable with a nil value, but with an
instantiated object. I guess that this has something to do with the
requirements of loading the objects properties from a dfm file.

2. Although the statement Datamodule1.cdsEmployee.Insert temporarily puts
the CDS cdsEmployee into the dsInsert state, and in so doing initialises the
new blank record by executing the OnNewRecord event handler assigned to
cdsEmployee, the state is changed at some point before the statement
FormEmployeeRecord.ShowModal is executed. Thus we end up seeing displayed
the record last focussed rather than a new blank record. Stepping through
the code using the debugger, it appears that because the CDS has a
calculated field, for some reason the event handler OnCalcFields is called,
and this changes the state from dsInsert to dsCalcFields. And what's worse,
it does not do this for just one record (the new blank record or the record
last focussed), but the calculated field is recalculated for every record in
the dataset.

It seems that once you start using many facilities of the client dataset
model, including several event handlers, the state of the CDS takes on 'a
mind of its own', and becomes very difficult to control! cdsEmployee also
has several other event handlers, including an AfterScroll event handler to
synchronise the cursor of a many-to-many detail dataset with that of
cdsEmployee. Some of these event handlers seem to switch the state of the
CDS. During debugging I inserted some MessageDlg or ShowMessage calls to
display the values of some variables, and these have the immediate effect of
switching the state of the CDS to Post.

All I wish to be able to do is to lock the state of the client dataset to
dsInsert until such time as I want to unlock it and allow the Delphi
frmework control it automatically. That's the reason for the inclusion of
the statement cdsEmployee.DisableControls. The form's OnShow event handler
calls cdsEmployee.EnableControls to re-establish the link between the
behaviour of the CDS and that of the data-aware controls.

Can anyone explain what is going on and how to avoid the undesired
behaviour?

TIA.

Enquiring Mind
Back to top
Kees Vermeulen (Kever-IT)
Guest





PostPosted: Wed Apr 11, 2007 5:10 pm    Post subject: Re: Problem with automatic switching of client dataset state Reply with quote



Enquiring Mind schreef:
Quote:
Hi,

I have a client dataset called cdsEmployee that contains data from the
EMPLOYEE table of the EMPLOYEE.GDB database. I have defined a form class
TFormEmployeeRecord that displays the fields of an individual record using
data-aware controls linked to cdsEmployee, but I have deleted the global
variable FormEmployeeRecord from the unit with the form's class, as I want
the form to be instantiated inside a procedure. I have included in the unit
2 global procedures called ShowEmployeeRecord and ShowNewEmployeeRecord
designed to be called from another form. These create an internal instance
of the TFormEmployeeRecord form, then show the form in modal mode. The
ShowNewEmployeeRecord is as follows:

procedure ShowNewEmployeeRecord;
var
FormEmployeeRecord: TFormEmployeeRecord;
begin
{if FormEmployeeRecord<>nil then
FreeAndNil(FormEmployeeRecord); }
FormEmployeeRecord:= TFormEmployeeRecord.Create(nil);
try
Datamodule1.cdsEmployee.DisableControls;
Datamodule1.cdsEmployee.Insert;
FormEmployeeRecord.ShowModal;
finally
FreeAndNil(FormEmployeeRecord);
end;
end;

The purpose of this procedure is to display an empty record in Insert mode.
However I have encountered the following problems:

1. The "if FormEmployeeRecord<>nil " statement (that is commented out ) does
not work as I would expect. Even though FormEmployeeRecord is declared as a
local variable of the procedure, and there is no global variable by the same
name, Delphi does not initialise the variable with a nil value, but with an
instantiated object. I guess that this has something to do with the
requirements of loading the objects properties from a dfm file.

Local variables are never initialized and contain random data on
procedure entrance.
BTW., given your code, this test is completely useless because you'll
have to create a new TFormEmployeeRecord anyway.

Quote:

2. Although the statement Datamodule1.cdsEmployee.Insert temporarily puts
the CDS cdsEmployee into the dsInsert state, and in so doing initialises the
new blank record by executing the OnNewRecord event handler assigned to
cdsEmployee, the state is changed at some point before the statement
FormEmployeeRecord.ShowModal is executed. Thus we end up seeing displayed
the record last focussed rather than a new blank record. Stepping through
the code using the debugger, it appears that because the CDS has a
calculated field, for some reason the event handler OnCalcFields is called,
and this changes the state from dsInsert to dsCalcFields. And what's worse,
it does not do this for just one record (the new blank record or the record
last focussed), but the calculated field is recalculated for every record in
the dataset.

It seems that once you start using many facilities of the client dataset
model, including several event handlers, the state of the CDS takes on 'a
mind of its own', and becomes very difficult to control! cdsEmployee also
has several other event handlers, including an AfterScroll event handler to
synchronise the cursor of a many-to-many detail dataset with that of
cdsEmployee. Some of these event handlers seem to switch the state of the
CDS. During debugging I inserted some MessageDlg or ShowMessage calls to
display the values of some variables, and these have the immediate effect of
switching the state of the CDS to Post.

All I wish to be able to do is to lock the state of the client dataset to
dsInsert until such time as I want to unlock it and allow the Delphi
frmework control it automatically. That's the reason for the inclusion of
the statement cdsEmployee.DisableControls. The form's OnShow event handler
calls cdsEmployee.EnableControls to re-establish the link between the
behaviour of the CDS and that of the data-aware controls.

Can anyone explain what is going on and how to avoid the undesired
behaviour?


Because your code calls DisableControls, you can no longer assume that
data aware controls are up to date and therefore your record editor will
fail.

You are saying that the dataset state is not set to dsInsert after the
call to Insert. This can only happen when your code is moving the record
cursor in some of the event handlers attached to this client dataset.
Every time the record position changes, TClientDataset will verify
whether this is OK and post any changes when necessary and, as a result,
the dataset state will be return to dsBrowse.

I think you would be better of using a cloned dataset for the record
edit window. A cloned dataset uses the same data as the original dataset
but has it's own cursor control. This enables you to insert a record in
the cloned dataset while scrolling through the original dataset. See the
manual on how to clone a TClientDataset.

Regards,

Kees
Back to top
Enquiring Mind
Guest





PostPosted: Wed Apr 11, 2007 8:53 pm    Post subject: Re: Problem with automatic switching of client dataset state Reply with quote



"Kees Vermeulen (Kever-IT)" <info (AT) kever (DOT) com> wrote in message
news:461cd0a4$1 (AT) newsgroups (DOT) borland.com...

Thanks for your comments.
Quote:

Because your code calls DisableControls, you can no longer assume that
data aware controls are up to date and therefore your record editor will
fail.

I'm not sure what you mean by 'your record editor will fail'. If you mean
that an exception will be generated as a result of the call to
DisableControls, I haven't experienced this so far. The purpose of disabling
the CDS controls is to uncouple the state of the CDS from that of the UI
during the creation of the form before the form becomes visible. The idea
was that when EnableControls is called in the OnShow event handler of the
form the connection between the controls and the CDS is reestablished, and
the controls then display the current state of the CDS. I initially didn't
include a call DisableControls, but added it in an attempt to prevent the
Delphi framework from changing the state of cdsEmployee from dsInsert to
some other state, since I thought that perhaps the initialisation of the
form's data-aware controls might be responsible for the change in state of
the CDS .
Quote:

You are saying that the dataset state is not set to dsInsert after the
call to Insert. This can only happen when your code is moving the record
cursor in some of the event handlers attached to this client dataset.
Every time the record position changes, TClientDataset will verify whether
this is OK and post any changes when necessary and, as a result, the
dataset state will be return to dsBrowse.

As far as I can make out the code that I have placed in the event handlers

attached to cdsEmployee does not move the cursor of the cdsEmployee dataset.
That's not to say, however, that the Delphi framework does not attempt to
scroll the dataset ... The form in question also displays a detail dataset
that is a junction table filtered by the current value of the Emp_No.

Quote:
I think you would be better of using a cloned dataset for the record edit
window. A cloned dataset uses the same data as the original dataset but
has it's own cursor control. This enables you to insert a record in the
cloned dataset while scrolling through the original dataset. See the
manual on how to clone a TClientDataset.


Thanks for this suggestion.

Regards,

Enquiring Mind
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Databases (dbExpress) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.