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