Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.02.20;
Скачать: CL | DM;

Вниз

Восстановление строк DBGrid после перезагрузки таблицы TQuery.   Найти похожие ветки 

 
Alex_S   (2005-01-04 21:04) [0]

Этот вопрос здесь уже немного обсуждался, но решения по-моему пока не было. Так что, если это кого-то ещё интересует, то пожалуйста:
Суть задачи следующая. Например, DBGrid показывает записи нередактируемого набора TQuery, запись изменяется через TTable, надо вернуть её в DBGrid так, чтобы она попала в ту же строку после перечитки TQuery.
Предлагаемое решение.
Для удобного вида можно в DBGrid1.Options включить dgRowSelect, чтобы ведялалсь вся строка.
Здесь важно определить, в какой строке (начиная с номера 1) из видимого списка DBGrid находилась редактируемая запись. Для этого предлагается следующая процедура обработки события DBGrid1.OnDrawDataCell:

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
  Field: TField; State: TGridDrawState);
begin
  if gdSelected in State then  NRow:= Rect.Top div 21;
{ при перерисовке ячеек DBGrid для выделенной ячейки определяем номер строки NReg - глобальная переменная типа integer;
  21 - высота строки. У себя проверьте эту величину.
  Для того, чтобы затем случайно она не изменилась в других экранных режимах для формы Form1 задайте свойство Scaled:=false }
end;

А теперь воспользуемся вычисленным номером NRow при перечитке TQuery:
При этом указатель сначала стоит на редактируемой записи (которая вносится в набор данных  - Table1.Post)

procedure TForm1.RereadQuery(Sender: TObject);
var k0: integer;
begin
 DBGrid1.DataSource:=nil; { так лучше }
 Query1.MoveBy(1-NRow); { обращаемся к верхней строке DBGrid"а }
 k0:=Query1.Fields.Fields[0].AsInteger;  { запоминаем значение Code этой записи -
  в задаче использовался набор данных с первым полем Code типа Autoinc }
 with Query1 do begin
   close;
   SQL.Clear;
   SQL.Add("SELECT * FROM <Имя_файла> ORDER BY CODE");
   Open;
 end;
 Query1.Locate("Code",k0,[]); { устанавливаем указатель на прежнюю верхнюю в DBGrid запись }
 DBGrid1.DataSource:=DataSource1;
 Query1.MoveBy(NRow-1); { теперь DBGrid двигаться не будет, устанавливаем указатель на измененную запись }
 DBGrid1.SetFocus; { и выделяем её }
end;

Метод не универсальный, но предложенную мысль уже можно развивать и подстраивать под свои потребности.


 
Vemer ©   (2005-01-05 10:23) [1]

с DBGrid (но не другими DB-Aware) прекрасно работает:

Dbgrid.dataSource.Dataset.DisableControls;
//тут запоминаем ID
Dbgrid.dataSource.Dataset.Close;
Dbgrid.dataSource.Dataset.Open;
//Dbgrid.dataSource.Dataset.Fetchall; если надо
Dbgrid.dataSource.Dataset.Locate на запомненный ID
Dbgrid.dataSource.Dataset.EnableControls;


 
msguns ©   (2005-01-05 10:35) [2]

>Vemer ©   (05.01.05 10:23) [1]

Текущей записью НД останется прежняя, а вот строка грида поменяется.


 
Alex_S   (2005-01-06 00:51) [3]

С учетом замечаний <<Vemer ©   (05.01.05 10:23) [1]>>
выполняем некоторые замены:
 
 { вместо DBGrid1.DataSource:=nil; ...}
 DBGrid1.DataSource.DataSet.DisableControls;
{ ... }
{ и вместо перезагрузки Query1 ... }
 DBGrid1.DataSource.DataSet.Close;
 DBGrid1.DataSource.DataSet.Open;
{ ... }
  { вместо DBGrid1.DataSource:=DataSource1; ...}
 DBGrid1.DataSource.DataSet.EnableControls;

Результат довольно приятный!


 
Alex_S   (2005-01-07 16:36) [4]

Поторопился я успокоиться, однако. Более подробное изучение вопроса приводит к следующему выводу:
способ DBGrid1.DataSource.DataSet.DisableControls работает хорошо, но строка попадает на середину DBGrid, поэтому, если раньше мы ориентировались на 1-ю строку, то теперь надо рассматривать среднюю. Если это учесть, то всё будет отлично. Таким образом, учтя все эти нюансы, окончательно получаем процедуру:

procedure TForm1.RereadQuery(Sender: TObject);
var k,k0,n: integer;
begin
 k:=Query1.Fields.Fields[0].AsInteger;
 n:=(DBGrid1.Height div 21) div 2; { номер средней строки в DBgrid1 }
 if Query1.RecordCount<n then n:=NRow; { Если записей мало }
 DBGrid1.DataSource.DataSet.DisableControls;
 Query1.Close; Query1.Open;
 Query1.Locate("Code",k,[]);
 Query1.MoveBy(n-NRow); { обращаемся к средней строке DBGrid"а }
 k0:=Query1.Fields.Fields[0].AsInteger; { запоминаем значение Code этой записи -
   в задаче использовался набор данных с первым полем Code типа Autoinc }
 Query1.Locate("Code",k0,[]); { устанавливаем указатель на среднюю в DBGrid запись }
 Query1.MoveBy(NRow-n); { теперь DBGrid двигаться не будет, устанавливаем указатель на измененную запись }
 DBGrid1.DataSource.DataSet.EnableControls; { оживляем DBGrid1 }
 DBGrid1.SetFocus; { и передаем ей фокус, если надо }
end;

 Здесь я также учёл, что в результате редактирования записи она может оказаться уже на новом месте в наборе данных - по условиям сортировки и проч.
 Поле Code здесь уникальное, поэтому запись все равно будет однозначно определена. Если кому-то покажется, что где-то
действия Locate и MoveBy лишние, то попробуйте сократить - мне кажется, они несколько по-разному работают с DBGrid.


 
Johnmen ©   (2005-01-20 22:59) [5]

Есть решение. Завтра приведу...
Спать охота...:)


 
Slym ©   (2005-01-21 07:49) [6]

А UpdateRecord не пробовал?


 
Alex_S   (2005-01-21 10:51) [7]

Читай внимательнее:
>DBGrid показывает записи нередактируемого набора TQuery!
------------------
Или уже научились применять UpdateRecord к такому набору?


 
msguns ©   (2005-01-21 12:03) [8]

Все эти фрикции с видимыми в гриде записями и выставлением нужной записи в нужной строке грида с помощью локэйтов на ID старых (до перечитки) записей эффективны лишь при условии, что с другого клиента не изменили состав записей, попавших в область "фрикций". А что, если с момента предыдущего открытия узеры за соседними столами поудаляли все записи, начиная от первой видимой и вплоть до текущей ? Или вставили кучу новых ? Что будет в рез-те ? А то, что узер после того, как жмякнул на кнопку "Записать" в модальной форме коррекции или добавления, увидит в гриде совсем другую запись. И обалдеет.
Кстати, этот "гениальный" алгоритм делания непонятно чего непонятно зачем почему-то не предусматривает удаления. Или я чего-то просмотрел ?


 
Vlad ©   (2005-01-21 12:24) [9]


> msguns ©   (21.01.05 12:03) [8]

Алгоритм действительно должен быть нетривиальный, а если еще учесть что эта запись могла быть удалена, тогда еще сложнее, т.к. понадобится инфа о соседней записи, для того чтобы она корректно встала на место удаленной (относительно грида)
Вобщем мне чего-то не оч. хочется ломать над этим голову, т.к. по-моему овчинка выделки не стоит...
ИМХО, проще реализовать Refresh отдельно взятой записи, тогда проблема сама собой отпадет.


 
Alex_S   (2005-01-21 12:38) [10]

Это не "универсальный солдат", а всего лишь некоторые частные решения. Никто не замахивается объять необъятное. На остальное опять же, кроме компонентов и проч., надо иметь и голову. И никто здесь на "гениальность" и не замахивается. Конечно, если ожидать всех остальных катаклизмов (куча юзеров меняет и удаляет записи), то лучше ничего не делать и не предлагать - так спокойнее. Всему свое место. Если я здесь один со своим набором данных, и я все знаю, что делаю, то могу спокойно это применять. В крайнем случае, самая большая беда, которая может произойти, это строка будет не на своем месте. Хотя я пока и не вижу причин такого. А если еще и с умом понаставить try...except, то вообще ничего никому не грозит.


 
msguns ©   (2005-01-21 13:16) [11]

>Alex_S   (21.01.05 12:38) [10]

Ну, по поводу гениальности обижаться-то не обязательно ;)
Ну просто я лично не вижу никакой необходимости в том, что измененная (добавленная) запись появлялась именно в том месте грида, где было выделение (текущая) до перечитки.
Но если уж приспичило, то я бы этот вопрос решал стриггридом, где полная возможность "рулежки" видимостью содержащихся в нем данных.

Тем более неясно, нафига "дибэйзовская" манера прокрутки грида относительно центральной строки. Для чего такие заморочки на ровном месте ? ИМХО, внимание при работе с БД надо уделять совершенно другим вещам. Хотя, конечно, это сугубо мое мнение и я его никому не навязываю.


 
Alex_S   (2005-01-21 14:28) [12]

2msguns
>Тем более неясно, нафига "дибэйзовская" манера прокрутки грида относительно центральной строки. Для чего такие заморочки на ровном месте ?
----------
Ну это к ним вопрос (борландцам). Чего им так нравится или середина, или начало (в другом способе).

>Ну просто я лично не вижу никакой необходимости в том, что измененная (добавленная) запись появлялась именно в том месте грида, где было выделение (текущая) до перечитки.
----------------
Это дело вкуса. Кому-то пофиг, а кому-то хочется.
Ну а стриггридом это крутить? Что-т сомнительно, чтобы большие БД можно было без проблем крутить не DB-ными компонентами.
Крутил я когда-то чем-то, пробовал уже, каждую запись (хоть и полей было немного) загружал в эти строки. Жуть! Даже при 1000 записей впечатление неприятное - ждать приходится!
Извращение это. Для того и придуманы DBGrid"ы и т.п.


 
Соловьев ©   (2005-01-21 15:23) [13]

>Суть задачи следующая. Например, DBGrid показывает записи
>нередактируемого набора TQuery, запись изменяется через TTable,
>надо вернуть её в DBGrid так, чтобы она попала в ту же строку
>после перечитки TQuery.

А почему через таблицу? Когда давно уже есть UpdateSQL или еще один запрос.
Почему она должна попасть в ту же строку? То как на экране(в гриде)
и то как в самой базе хранятся записи - никак не связано. Если хочешь какой-то порядок, то есть сортировка.



Страницы: 1 вся ветка

Текущий архив: 2005.02.20;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.044 c
14-1106986303
kaZaNoVa
2005-01-29 11:11
2005.02.20
Посоветуйте Антивирус, какой лучше?


6-1102415874
Prankster.
2004-12-07 13:37
2005.02.20
Получение файла из сети


14-1106859717
Delphin
2005-01-28 00:01
2005.02.20
Hi All! Не могли бы вы помочь решить другую задачку:


4-1104759069
Сергей+
2005-01-03 16:31
2005.02.20
Инвертирование цвета


1-1107356958
JuryL
2005-02-02 18:09
2005.02.20
MDI и потоки