Но, вполне приятная штука для создания дерева из данных в 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;



