Einzelnen Beitrag anzeigen

Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#19

Re: Anzeigeproblem bei eigener DB-Text-Komponente auf DBCtrl

  Alt 26. Jan 2007, 13:46
Hallo Martin,

also meine Komponenten funktionieren in DBCtrlGrid gar nicht (müssen sie aber auch nicht). DBEditSql (abgeleitet von DBEdit) lässt sich nicht einmal in das Grid einbinden.
Das Grid übernimmt offenbar die Kontrolle über die eingebunden Kompos, ordnet denen seine eigene interne Datenmenge zu und gibt möglicherweise sogar vor, wann diese Kompos neue Dateninhalte anzeigen sollen (sonst würden sie möglicherweise alle den Inhalt des aktuellen Datensatzes anzeigen).
Wenn das so ist, muss das Grid aber die eingebunden Komponenten kennen, um diese für seine Zwecke umzubiegen...

Mit dem FieldDataLink musst Du Dich m.E. nur näher beschäftigen, wenn Du mehrere Datensätze in Deiner Komponente verwalten willst (wie ein DBGrid).

Ansonsten reicht es, einfach nur FieldDataLink einzubinden. So habe ich es für meine Ein-Datensatz-Komponente gemacht:
Delphi-Quellcode:
//
constructor TDBSqlCustom.Create(AOwner: TComponent);
begin
  inherited;
  FFieldDataLink:=TFieldDataLink.Create;
  FieldDataLink.Control:=Self;
  FieldDataLink.OnDataChange:=DataChange;
...

//
procedure TDBSqlCustom.SetDataSet(Value:TDataSet);
begin
  if ((FieldDataLink<>nil) and (FieldDataLink.DataSource<>nil)) then begin
    if (Value<>FieldDataLink.DataSource.DataSet) then begin
      FieldDataLink.DataSource.DataSet:=Value;
      ShowData(True); // Datensatzinhalt anzeigen
    end;
  end;
...

procedure TDBSqlCustom.SetFieldName(Value:String);
begin
  if (FFieldName<>Value) then begin
    FField:=nil;
    FFieldName:=Value;
    FFieldDataLink.FieldName:=FFieldName;
    ShowData(True);
...

procedure TDBSqlCustom.SetDataSource(Value:TDataSource);
begin
  if ((FFieldDataLink<>nil) and (FFieldDataLink.DataSource<>Value)) then begin
    ResetFields(True);
    FFieldDataLink.DataSource:=nil;
    FFieldDataLink.FieldName:='';
    if (not (FFieldDataLink.DataSourceFixed and (csLoading in ComponentState))) then FFieldDataLink.DataSource:=Value;
    if (Value<>nil) then Value.FreeNotification(Self);
    ShowData(True);
...

Für mehrere Datensätze habe ich einen ausreichend großen Puffer für die anzuzeigenden Datensätze angelegt:
FieldDataLinkShow.BufferCount:=100; (wobei ich mehrere Datenmenge syncronisiere und deshalb die Puffergrößen aufeinander abstimmen muss)

Mit FieldDataLinkShow.ActiveRecord:=FieldDataLinkShow. ActiveRecord+-1 kannst Du durch die Datensätze iterieren, ohne dass dies Auswirkungen auf angebundene datensensitive Komponenten hat.
Wenn Du außerhalb des definierten Pufferbereiches kommst, erhältst Du nur noch leere Dateninhalte.

TDBSqlWhere kapselt die ganze Datenbankverbindung und wird von meinen TDBTabControlSql und TDBPanelsSql jeweils benutzt, um "die jeweils nächsten" Datensätze bereitzustellen. Die beiden Komponenten wiederum geben Ihrerseits vor, wann die Dateninhalte der einzelnen Items gezeichnet werden müssen:
Delphi-Quellcode:
//------------------------------------------------------------------------------
//
procedure TDBSqlWhere.SetDBSqlBufferCount(MaxCount:Integer);
var NeedBufferCount:Integer;
begin
  if (MaxCount=0) then MaxCount:=MinBufferCount;
  if ((MaxCount>0) and (RecordCount>0)) then NeedBufferCount:=Min(RecordCount,MaxCount)
  else NeedBufferCount:=RecordCount;
  DBSqlBufferSize:=Max(DBSqlBufferSize,NeedBufferCount);
  if (FieldDataLinkShow.BufferCount<DBSqlBufferSize) then FieldDataLinkShow.BufferCount:=DBSqlBufferSize;
end;

//------------------------------------------------------------------------------
//
procedure TDBSqlWhere.BeginReadRecord(RR:Integer=-1);
begin
  if (RR>0) then FieldDataLinkShow.ActiveRecord:=RR;
  if (FieldDataLinkShow<>nil) then begin
    ActiveDBSqlRecNo:=DataSetShow.RecNo;
    ActiveDBSqlRecord:=FieldDataLinkShow.ActiveRecord;
  end
  else begin
    ActiveDBSqlRecNo:=0;
    ActiveDBSqlRecord:=0;
  end;
  FirstDBSqlRecNo:=ActiveDBSqlRecNo;
  LastDBSqlRecNo:=ActiveDBSqlRecNo;
  ReadDBSqlRecNo:=ActiveDBSqlRecNo;
  FirstDBSqlRecord:=ActiveDBSqlRecord;
  LastDBSqlRecord:=ActiveDBSqlRecord;
  ReadDBSqlRecord:=ActiveDBSqlRecord;
end;

//------------------------------------------------------------------------------
//
function TDBSqlWhere.GetReadRecord(RR:Integer):Boolean;
begin
  Result:=False;
  if ((RR>=0) and (RR<RecordCount)) then begin
    if ((RR<FirstDBSqlRecord) or (FirstDBSqlRecord<0)) then FirstDBSqlRecord:=RR;
    if (RR>LastDBSqlRecord) then LastDBSqlRecord:=RR;
    FieldDataLinkShow.ActiveRecord:=RR;
    Result:=True;
  end;
end;

//------------------------------------------------------------------------------
//
function TDBSqlWhere.ReadRecordIsActive:Boolean;
begin
  Result:=(FieldDataLinkShow.ActiveRecord=ActiveDBSqlRecord);
end;

//------------------------------------------------------------------------------
//
procedure TDBSqlWhere.GoToRecNo(RN:Integer);
begin
  inherited;
  if (DataSetShow<>nil) then begin
    if (RN>RecordCount) then RN:=RecordCount;
    if (RN>0) then DataSetShow.RecNo:=RN;
  end;
end;

//------------------------------------------------------------------------------
//
procedure TDBSqlWhere.EndReadRecord;
begin
  if (FieldDataLinkShow<>nil) then FieldDataLinkShow.ActiveRecord:=ActiveDBSqlRecord;
end;
Das sind zwar etwas ältere Quelltexte, das Prinzip sollte aber erkennbar sein...

Gruß Stahli
  Mit Zitat antworten Zitat