Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];

Вниз

Восстановление строк 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.035 c
4-1105022351
N0th!ng
2005-01-06 17:39
2005.02.20
Прозрачное окно


1-1107534792
Fostr
2005-02-04 19:33
2005.02.20
RichEdit масштаб


9-1099760624
Xeno
2004-11-06 20:03
2005.02.20
Анимация MD3 в GLScene


14-1107349002
Nifrit
2005-02-02 15:56
2005.02.20
проблема с Com портом


1-1107773125
salexn
2005-02-07 13:45
2005.02.20
Excel





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский