C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Родной DBGridEh, задать номер первой отображаемой записи
Deem
Отправлено: 17.01.2006, 11:08


Мастер участка

Группа: Участник
Сообщений: 327



Очень надо: задать номер первой отображаемой записи, т.е. после полного рефреша запроса (Active = false; Active = true;) выйти на тот же вид сетки (на активную запись курсор перегнать могу, этого мало!), что и до рефреша.
avc*
Отправлено: 17.01.2006, 14:03


Не зарегистрирован







Думаю ему нужно следующее — если верхней в сетке была запись с PK = 5 то и после refresh'а она должна быть там же. Можно достигнуть "точной" подгонкой dataset'а, например функциями DataSet->MoveBy (вычисленное смещение);
olegenty
Отправлено: 17.01.2006, 14:27


Ветеран

Группа: Модератор
Сообщений: 2412



ну на нужную запись по PK можно и с помощью Locate выйти. тогда я всё-таки не понял, что требуется.
avc*
Отправлено: 17.01.2006, 15:35


Не зарегистрирован







QUOTE

ну на нужную запись по PK можно и с помощью Locate выйти. тогда я всё-таки не понял, что требуется

Я имел ввиду следующее — ну стал ты локатом на нужную запись, а оно должна в быть, допустим, в седьмой строке грида.
olegenty
Отправлено: 17.01.2006, 15:39


Ветеран

Группа: Модератор
Сообщений: 2412



вот теперь понятно. мне пока этого ни разу не было нужно.
avc*
Отправлено: 17.01.2006, 15:42


Не зарегистрирован







Мне тоже. smile.gif
Но я могу и ошибаться и Deem имел ввиду нечто другое.
Deem
Отправлено: 17.01.2006, 17:43


Мастер участка

Группа: Участник
Сообщений: 327



Спасибо за такое участие!!! biggrin.gif

Правильно понял AVC. Если делать мягкий рефреш, т.е. при помощи апдейтскуель рефрешить текущую строку — все классно. Но может пригодиться только в случае езменения записи, да и то, если фильтры не задевают изменения (рефрешуемая запись может после изменения не пролазить в фильтр). У меня изменение данных идет строго через диалоги, сетка не знает изменений, пока не дашь команду рефрешить. А добавление и удаление записи не отследит даже тогда, только при включении/выключении датасета. Я уж не говорю про ситуацию, когда база по сети работает, и надо на всех клиентах обновить данные по событию сервера.

Короче, в очень многих случаях надо делать выключение/включение датасета. И даже если я выставлю курсор на ту запись, где она стояла до этого, общая картинка сетки может съехать . Хочу сделать рефрешь так, чтобы юзер не заметил.

Для этого надо заблокировать отображение и после активации запроса выставить ту запись в самый верх грида, которая было до этого.

Не смог, как ни старался, выйти на запись, которая видна в самом верху грида.

" Можно достигнуть "точной" подгонкой dataset'а, например функциями DataSet->MoveBy (вычисленное смещение);"

Посмотрю этот вариант, хотя пока не понял, где можно использовать.

avc*
Отправлено: 17.01.2006, 18:13


Не зарегистрирован







QUOTE

Посмотрю этот вариант, хотя пока не понял, где можно использовать.

Например при рефреше. Можно попытаться достутачаться до TCustomGrid::Row и на разностях до и после рефреша подсчитать смещение.
Deem
Отправлено: 17.01.2006, 18:47


Мастер участка

Группа: Участник
Сообщений: 327



Попробуем.
Johnick
Отправлено: 13.02.2006, 11:58


Не зарегистрирован







Уважаемый, Deem. У меня возникла такая же проблема, что и у тебя.
Пишу локальную базу Paradox. Использую компонент TTable и DBGrid. Данные, которые я получаю по последовательному порту необходимо вносить в эту базу. Данные приходят с периодом 1...2 мин. Так вот, когда данные пишутся в базу, то в DBGrid происходит смещение, хотя я и возвращаюсь на нужную запись, которая была до записи пришедших данных. Удалось ли тебе решить эту проблему?
bmv
Отправлено: 13.02.2006, 18:25


Ученик-кочегар

Группа: Участник
Сообщений: 7



Что-то наподобие я делал с помощью Bookmark, не знаю может поможет.
CODE

   TDataSet *pDS = DBGrid->DataSource->DataSet;
   DBGrid->Visible = false;
   // Запоминаем положение курсора
   TBookmark SavePlace = pDS->GetBookmark();
   // Что-то делаем..
   // ...
   // Восстанавливаем первоначальное положение курсора
   pDS->GotoBookmark(SavePlace);
   pDS->FreeBookmark(SavePlace);
   // Перерисовываем
   DBGrid->Visible = true;
   DBGrid->Repaint();
olegenty
Отправлено: 14.02.2006, 08:16


Ветеран

Группа: Модератор
Сообщений: 2412



2 bmv:
1. Это не гарантирует неизменного положения записи в гриде.
2. Это вообще ничего не гарантирует (никто не сказал, что Bookmark будет Valid после Refresh), и лучше пользоваться Locate.
Johnick
Отправлено: 14.02.2006, 10:14


Не зарегистрирован







to BMV:
Спасибо за помощь, но к сожалению это не помогло.

to OLEGENTY:
Спасибо. Locate использовал, тоже не помогает.

Какие есть еще мнения? Может есть какой нибудь метод у грида, чтобы нужная (выбранная) мне запись появлялась в нужной строке грида?
olegenty
Отправлено: 14.02.2006, 11:30


Ветеран

Группа: Модератор
Сообщений: 2412



и не должно. см. ответ AVC, он похож на правду.
bmv
Отправлено: 14.02.2006, 12:13


Ученик-кочегар

Группа: Участник
Сообщений: 7



QUOTE (Johnick @ 14/02/2006, 10:14)
Какие есть еще мнения? Может есть какой нибудь метод у грида, чтобы нужная (выбранная) мне запись появлялась в нужной строке грида?

Если все, что было тут перечислено не помогает, то уже ничего не поможет. Если только вывести новый класс из DBGrid и самому там что-нибудь сделать smile.gif
Я вообще этим компоннетом редко пользуюсь как раз из-за его недостаточной "управляемости".
AVC
Отправлено: 14.02.2006, 16:27


Ветеран

Группа: Модератор
Сообщений: 1583



Проверенный вариант стабильного курсора в TDBGrid
(не проверял на маленьких выборках) (проверил, работает)
CODE

//---------------------------------------------------------------------------
// Static DBGrid cursor
//---------------------------------------------------------------------------

class tmpTDBGrid : public TDBGrid
{public:
int __fastcall GetRow (void);
int __fastcall GetRowCount (void);
};

int __fastcall tmpTDBGrid::GetRow (void) { return TCustomGrid::Row; }
int __fastcall tmpTDBGrid::GetRowCount (void)
{
return TCustomGrid::RowCount — ((TDBGrid::Options.Contains(dgTitles))? 1 : 0);
}

//- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - -

void __fastcall TForm1::Button9Click(TObject *Sender)
{
TDBGrid *grd = DBGrid1;
TDataSet *ds = grd->DataSource->DataSet;
if (!ds) return;
if (!ds->Active)
{ ds->Active = true;
return;
}

// Запомнить текущую строку в сетке
tmpTDBGrid *tgrd = (tmpTDBGrid*)grd;
int oldri = tgrd->GetRow();
int oldID = ds->FieldByName("ID")->AsInteger;

ds->DisableControls();
try {
ds->Active = false;
ds->Active = true;

// Восстановить позицию на запись
ds->Locate("ID", oldID, TLocateOptions());
int newri = tgrd->GetRow();

int vrc = tgrd->GetRowCount(); // visible row count
if (oldri > vrc / 2) // строка из нижней половины — крутить назад
{ ds->MoveBy((1-newri) — (oldri — newri));
ds->MoveBy(oldri-1);
}
else // строка из верхней половины — крутить вперед
{ ds->MoveBy(vrc — oldri);
ds->MoveBy(oldri — vrc);
}

} // try DisableControls
__finally { ds->EnableControls(); }

grd->SetFocus();
}
//---------------------------------------------------------------------------


Отредактировано AVC — 14/02/2006, 15:28
Johnick
Отправлено: 15.02.2006, 16:33


Не зарегистрирован







to AVC:
Спасибо огромное. Все заработало как часы. smile.gif

Вернуться в Работа с базами данных в C++Builder