TVirtualDBTreeEx

Модератор: Модераторы

TVirtualDBTreeEx

Сообщение Sharfik » 10.04.2025 01:14:38

На базе TVirtualStringTree есть компонент TVirtualDBTreeEx. Немного тут на форуме его упоминали, он древний и не развивается судя по github https://github.com/adem0x/virtualdbtreeex
Но, вполне приятная штука для создания дерева из данных в DataSet. Так вот. Экспериментируя с tcp соединением стал передавать данные из БД в TBufDataset который является входным буфером. Из буфера данные копируются уже в DataSet на который завязаны компоненты формы. Чтобы интерфейс не прыгал и не рушилась структура открытых\закрытых нодов дерева используется синхронизация данных между DataSet-ами, а не тупое копирование. Код ниже.
И вот тут вылез косяк... Если функция синхронизации заключена в DisableControls\EnableControls, то имеющиеся записи в TVirtualDBTreeEx могут удаляться, добавляться, но вот просто изменить текст поля - нет. Если не блокировать компоненты все нормально, но скачет фокус и положение скролла. С другими компонентами проблемы нет.
В какую сторону рыть? не пойму. Нужно как то найти действия компонента при EnableControls у DataSets.

Простой тест
Код: Выделить всё
function TestFieldData(AToDataSet: TBufDataset): Boolean;
begin
  AToDataSet.DisableControls;
  try
     AToDataSet.Edit;
     AToDataSet.FieldByName('name').Value:='test';
     AToDataSet.Post;
  except
     AToDataSet.CancelUpdates;
  end;
AToDataSet.EnableControls;
end; 


Полный код

Код: Выделить всё
function SynchronizationDataSet(AFromDataSet,AToDataSet: TBufDataset): Boolean;
var
  MS: TMemoryStream;
begin
   Result:=False;
   if AToDataSet.RecordCount>0 then
   begin
     Result:=SynchronizationDataSetRecords(AFromDataSet,AToDataSet);
   end
   else begin
     AToDataSet.DisableControls;
     try
        MS:=TMemoryStream.Create;
        MS.Position:=0;
        AFromDataSet.SaveToStream(MS);
        MS.Position:=0;
        AToDataSet.LoadFromStream(MS);
        AToDataSet.First;
        Result:=True;
     finally
        MS.Free;
     end;
     AToDataSet.EnableControls;
   end;
end;   


Код: Выделить всё
//Синхронизирует данные в dataset
function SynchronizationDataSetRecords(AFromDataSet,AToDataSet: TBufDataset): Boolean;
var
  sFieldName        :ShortString;
  i                 :integer;
  iBookmarkIndex    :LongInt;
  bRecExists        :Boolean;
  fTo,
  fFrom             :TField;
begin
  Result:=True;
  try
     iBookmarkIndex:=GetDataSetCurIndex(AToDataSet);
     //
     if iBookmarkIndex>0 then
     begin

         for i:=0 to AFromDataSet.Fields.Count-1 do
         begin
            fFrom      :=AFromDataSet.Fields.Fields[i];
            sFieldName :=fFrom.FieldName;
            fTo        :=AToDataSet.FieldByName(sFieldName);
            if not Assigned(fTo) then
            begin
                AToDataSet.FieldDefs.Add(fFrom.FieldName,fFrom.DataType,fFrom.Size,fFrom.Required);
                AToDataSet.FieldDefs.Find(fFrom.FieldName).CreateField(AToDataSet);
            end
            else begin
                if fTo.DataType<>fFrom.DataType then
                begin
                   Result:=False;
                end;
            end;
         end;

         if Result then
         begin
           //Добавляем новые записи
           AFromDataSet.First;
           while not AFromDataSet.EOF do
           begin

               bRecExists:=False;
               AToDataSet.First;
               while not AToDataSet.EOF do
               begin
                    if VarCompareValue(AFromDataSet.FieldByName('id').Value,AToDataSet.FieldByName('id').Value)=vrEqual then
                    begin
                      bRecExists:=True;
                      break;
                    end
                    else begin
                      AToDataSet.Next;
                    end;
               end;

               if not bRecExists then
               begin
                  //Добавляем новые записи
                  AToDataSet.Append;
                  CopyRecordFieldData(AFromDataSet,AToDataSet);
               end;

             AFromDataSet.Next;
           end;

           //Обновляем существующие
           ////Некоторые компоненты не обрабатывают изменения
           //данных после DisableControls/EnableControls
           AFromDataSet.First;
           while not AFromDataSet.EOF do
           begin

               bRecExists:=False;
               AToDataSet.First;
               while not AToDataSet.EOF do
               begin
                    if VarCompareValue(AFromDataSet.FieldByName('id').Value,AToDataSet.FieldByName('id').Value)=vrEqual then
                    begin
                      bRecExists:=True;
                      break;
                    end
                    else begin
                      AToDataSet.Next;
                    end;
               end;

               if bRecExists then
               begin
                   //Обновляем существующие
                  CopyRecordFieldData(AFromDataSet,AToDataSet);
               end;

             AFromDataSet.Next;
           end;

           //Удаляем отсутствующие
           AToDataSet.First;
           while not AToDataSet.EOF do
           begin

               bRecExists:=False;
               AFromDataSet.First;
               while not AFromDataSet.EOF do
               begin
                    if VarCompareValue(AFromDataSet.FieldByName('id').Value,AToDataSet.FieldByName('id').Value)=vrEqual then
                    begin
                      bRecExists:=True;
                      break;
                    end
                    else begin
                      AFromDataSet.Next;
                    end;
               end;

               if not bRecExists then
               begin
                  AToDataSet.Delete;
               end;

             AToDataSet.Next;
           end;
         end;

     end;
     //
     SetDataSetCurIndex(AToDataSet,iBookmarkIndex);

  except
     Result:=False;
     if AToDataSet.Active then
     AToDataSet.CancelUpdates;
  end;
end;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 807
Зарегистрирован: 20.07.2013 01:04:30

Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

Рейтинг@Mail.ru