Datasource dataChange firing lots when changing column widths

Datasource dataChange firing lots when changing column widths

Post by JAC » Fri, 05 Dec 2003 10:32:22


Hi All,

I am about to look into this further, but thought one of you might have a
rational explanation.

Minimal reconstruction.
clientdataset <- datasource <- grid

Open dataset, datasources onDataChange fires 1x
issue something like
dbgrid.columns[0].Width:=dbgrid.columns[0].Width+1 and fire 0 .. 9 times,
randomly it appears.

I noticed that an old BDE application with a Master Detail relationship,
where the detail was getting refreshed by the OnDataChange of the master was
firing far too often. It is a fairly complicated UI so I whittled it down
to a simple 1 form app with the above + a button to open the dataset and
another to grow the columns.

What I don't like is that the event should not be firing as no data is
changing, any ideas?

JAC
 
 
 

Datasource dataChange firing lots when changing column widths

Post by CheshireCa » Sat, 06 Dec 2003 00:49:29

Hi Jason,

I did the same with a ttable <- datasource <-grid
If i just linked the grid to the datasource I got the same as you
When I created a column manually in the grid, for each of the fields in the
table, using the column editor, I didnt get the change event fired

CheshireCat

 
 
 

Datasource dataChange firing lots when changing column widths

Post by CheshireCa » Sat, 06 Dec 2003 00:56:12

The following is a list of the callstack when the event fires.
deLayoutChange forces a datachange event.

TForm1.DataSource1DataChange(???,???)
TDataSource.DataEvent(deLayoutChange,0)
TDataSet.DataEvent(deLayoutChange,0)
TBDEDataSet.DataEvent(deLayoutChange,0)
TTable.DataEvent(deLayoutChange,0)
TField.PropertyChanged(True)
TField.SetDisplayWidth(15)
TColumn.SetWidth(79)
TCustomDBGrid.ColWidthsChanged
TCustomGrid.SetColWidths(1,79)
TCustomGrid.MouseUp(mbLeft,[],93,9)
TCustomDBGrid.MouseUp(mbLeft,[],93,9)
TControl.DoMouseUp((514, 0, 93, 9, (93, 9), 0),mbLeft)
TControl.WMLButtonUp((514, 0, 93, 9, (93, 9), 0))
TControl.WndProc((514, 0, 589917, 0, 0, 0, 93, 9, 0, 0))
TWinControl.WndProc((514, 0, 589917, 0, 0, 0, 93, 9, 0, 0))
TWinControl.MainWndProc((514, 0, 589917, 0, 0, 0, 93, 9, 0, 0))
StdWndProc(4588762,514,0,589917)
TApplication.HandleMessage
TApplication.Run
Project1
 
 
 

Datasource dataChange firing lots when changing column widths

Post by JAC » Sat, 06 Dec 2003 02:45:16

CheshireCat (Nice Name, from Cheshire or grinning like?)

Thanks for the reply - how did you get such a full call stack, I got:
TForm1.DataSource1DataChange(???,???)

I can now se why it happens, although I think it is still bad - maybe they
should have two events or more data inthe event e.g.
eventType = (etScroll, etFormat, etDisplayFormat) then you could decide what
you wanted to do, instead of a blunderbus (sp) approach which, until I
noticed, made for a lot of data access.

This seems promising:
TDataSource.DataEvent(deLayoutChange,0)

Implementation:
procedure TDataSource.DataEvent(Event: TDataEvent; Info: Longint);
begin
if Event = deUpdateState then UpdateState else
if FState <> dsInactive then
begin
NotifyDataLinks(Event, Info);
case Event of
deFieldChange:
if Assigned(FOnDataChange) then FOnDataChange(Self, TField(Info));
deRecordChange, deDataSetChange, deDataSetScroll, deLayoutChange:
if Assigned(FOnDataChange) then FOnDataChange(Self, nil);
deUpdateRecord:
if Assigned(FOnUpdateData) then FOnUpdateData(Self);
end;
end;
end;

Why don't they make these things virtual protected - that would give me half
a chance.

I don't want to create persistant TColumns as my system is more RAD by
setting the dataset, then I have a Form.onResize which stretches the columns
so that there is no horizontal scrollbar.

Back to the drawingboard. I think I might write some generic code that
creates the TColumns, steals the propertions from the dataset and then
manipulate the TColumns. So my form will:
1) get dataaset
2) create Tcolumns in the same way as I guess the VCL must when I don't
supply them
3) Proportion them, which if you are right will not fire the datasource
event
4) Hook up the datasource.

Is there a way to turn make the DBGrid to think the TCOlumns are its own,
i.e. at desgin time and as such not pass the message onto the relevant
dataset. More code digging required.

Looked at:
procedure SetWidth(Value: Integer); virtual;
but it is private, so I can't inherit from it:-)

Thanks for the insightful debug stuff.


JAC
 
 
 

Datasource dataChange firing lots when changing column widths

Post by CheshireCa » Sat, 06 Dec 2003 05:00:38


Just turn on "use debug dcus" in compiler options then do a rebuild

have fun
CheshireCat