D6 профессор.
Раньше мы использовали DBISAM и DBISAMTable. Тот дескриптор RecNo, и это работает хорошее с модификациями (Удалите, отредактируйте, и т.д.).
Теперь мы заменили ElevateDB, которые не обрабатывают RecNo, и много раз мы используем Запросы, не Таблицы.
Запрос должен вновь открыться для наблюдения модификаций.
Но если мы Вновь открыли Запрос, нам нужно к тому, чтобы менять местоположение к последней записи. Найдите не достаточно, потому что Сетка является шоу это в другой строке. Это - очень тревожащая вещь, потому что после того, как запись модификации перемещается в другую строку, Вы трудно для следования за нею, и пользователи ненавидят это.
Мы нашли этот код:
function TBaseDBGrid.GetActRow: integer;
begin
Result := -1 + Row;
end;
procedure TBasepDBGrid.SetActRow(aRow: integer);
var
bm : TBookMark;
begin
if IsDataSourceValid(DataSource) then with DataSource.DataSet do begin
bm := GetBookmark;
DisableControls;
try
MoveBy(-aRow);
MoveBy(aRow);
//GotoBookmark(bm);
finally
FreebookMark(bm);
EnableControls;
end;
end;
end;
Исходным примером является использование moveby. Эта работа, хорошая с Запросами, потому что мы не видим, что Запрос, вновь открытый в фоновом режиме, визуальный контроль, не сменился положение строки.
Но когда у нас есть EDBTable или Живой/Чувствительный Запрос, MoveBy опасен для использования, потому что, если кто-то удаляет или добавляет новую строку, мы можем переместить в неправильную запись.
Затем я пытался использовать BookMark (см. комментарий). Но эта техника не работает, потому что это - шоу запись в другом положении строки...
Так вопрос: как вынудить обоих положение строки и запись в DBGrid?
Или какой DBGrid может переместить к записи/строке после базового обновленного DataSet?
Я ищу удобное для пользователя решение, я понимаю их, потому что я пытался использовать этот переход - через DBGrid и очень плохо использовать, потому что мои глаза выходят когда попытка найти исходную запись после обновления... :-(
Спасибо за Вашу каждую справку, ссылку, информацию: dd
Поскольку MoveBy работают на вас, используйте их.
Установите закладку перед закрытием набора данных. Выполняйте свою работу, повторно откройте набор данных, а затем переместите свою запись в сетку с помощью «MoveBy's. Когда вы закончите, получите еще одну закладку и сравните ее с предыдущей с помощью DataSet.CompareBookmarks. Если результат 0 - нормально, если нет, то только тогда сделайте «GotoBookmark» для предыдущей закладки.
Таким образом, пока другой пользователь не удалил / не вставил записи, ваша сетка не будет казаться скачкообразной, а если это не так, по крайней мере, вы будете в той же записи.
редактировать: Вот пример кода, который должен переставить выбранную запись в правильное место, даже если в наборе данных были операции удаления / вставки. Обратите внимание, что в коде отсутствуют элементы управления отключением / включением, а также особый случай, когда меньше записей для заполнения сетки для простоты.
type
TAccessDBGrid = class(TDBGrid);
procedure TForm1.Button1Click(Sender: TObject);
var
BmSave, Bm: TBookmark;
GridRow, TotalRow: Integer;
begin
GridRow := TAccessDBGrid(DBGrid1).Row;
TotalRow := TAccessDBGrid(DBGrid1).RowCount;
BmSave := DBGrid1.DataSource.DataSet.GetBookmark;
try
// close dataset, open dataset...
if DBGrid1.DataSource.DataSet.BookmarkValid(BmSave) then
DBGrid1.DataSource.DataSet.GotoBookmark(BmSave);
Dec(TotalRow);
if GridRow < TotalRow div 2 then begin
DBGrid1.DataSource.DataSet.MoveBy(TotalRow - GridRow);
DBGrid1.DataSource.DataSet.MoveBy(GridRow - TotalRow);
end else begin
if dgTitles in DBGrid1.Options then
Dec(GridRow);
DBGrid1.DataSource.DataSet.MoveBy(-GridRow);
DBGrid1.DataSource.DataSet.MoveBy(GridRow);
end;
Bm := DBGrid1.DataSource.DataSet.GetBookmark;
try
if (DBGrid1.DataSource.DataSet.BookmarkValid(Bm) and
DBGrid1.DataSource.DataSet.BookmarkValid(BmSave)) and
(DBGrid1.DataSource.DataSet.CompareBookmarks(Bm, BmSave) <> 0) then
DBGrid1.DataSource.DataSet.GotoBookmark(BmSave);
finally
DBGrid1.DataSource.DataSet.FreeBookmark(Bm);
end;
finally
DBGrid1.DataSource.DataSet.FreeBookmark(BmSave);
end;
end;
Сохраните значение(я) поля(й) уникального ключа перед закрытием и повторным открытием запроса, затем Найдите
запись после повторного открытия. DisableControls
/EnableControls
для предотвращения обновления экрана.
Просто простой фрагмент кода, который пришел мне в голову:
procedure DoRefresh(Dataset: TDataset);
var
bkm: TBookmark;
begin
Dataset.UpdateCursorPos;
bkm := Dataset.GetBookmark;
Dataset.DisableControls;
try
Dataset.Refresh; //refresh dataset if it's open
if Dataset.BookmarkValid(bkm) then
begin
Dataset.GotoBookmark(bkm);
end;
finally
Dataset.EnableControls;
Dataset.FreeBookmark(bkm);
end;
end;
Позиция записи во многом зависит от порядка сортировки набора результатов, полученного из объекта Query / Table. Если вы не заказываете вообще, порядок, который вы получаете от сервера, определяется реализацией и так далее, не может гарантировать, что записи поступят в том же порядке при повторном открытии запроса , даже если никаких изменений не произошло . По крайней мере, в MSSQL и Firebird результаты приходят в разном порядке, если не используется предложение Order By .
Что касается изменения положения, я считаю, что решение TOndrej является наиболее безопасным - использование первичного ключа набора результатов для изменения положения сетки на правой записи.