Форум: "Базы";
Текущий архив: 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.039 c