Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > DataControls не изменяют DataSet в нужный момент


Автор: ZVano 15.12.2010, 13:58
Проблемма со стандартными компонентами ввода данных (TDBLookupComboBox, TDBCheckBox и т.д.).
Эти компоненты модифицируют набор данных DataSet только в момент потери фокуса. (OnExit)
Мне нужно заставить компонент выполнить модификацию в любой момент.
Например: 
Пользователь выбрал строку из выпадающего списка TDBLookupComboBox, но компонент фокус не потерял.
Решил этот момент таким костылем:
Код

void __fastcall TfrmDocsEdit::dcbDocTypeCloseUp(TObject *Sender) {
    TWinControl * workControl = ActiveControl;
    FindNextControl(workControl, true, true, false)->SetFocus();//Переходим на следующий контрол
    workControl->SetFocus();//Возвращаем фокус обратно, чтобы пользователь ничего не заметил
}

Т.е. отловил момент закрытия списка выбора и принудительно переключил фокус на след.контрол, затем вернулся на предыдущий.
Этот костыль хоть и не нравится мне, но все же работает.

А как быть с TDBCheckBox? 
Пользователь может кликать по нему до посинения, а DataSet не изменится.
Попытка сместить фокус в обработчике OnClick вызывает исключение.
Код

void __fastcall TfrmDocsEdit::dcbDocIsActiveClick(TObject *Sender) {
    TWinControl * workControl =    ActiveControl;
    FindNextControl(workControl, true, true, false)->SetFocus();
    workControl->SetFocus();
}

Получаю жуткую ошибку "Abnormal program termination".

Вобщем, нужно сделать так, чтобы при редактировании данных в контроле они тут-же изменяли DataSet.
Либо корректно делать это обрабатывая события ввода.

Автор: _Dimon_ 16.12.2010, 14:19
Код

void __fastcall TfrmDocsEdit::dcbDocTypeCloseUp(TObject *Sender) 
{
 dynamic_cast<TDBLookupComboBox*>(Sender)->DataSource->DataSet->Post();
}

Автор: ZVano 16.12.2010, 16:57
Цитата(_Dimon_ @ 16.12.2010,  14:19)

Код

void __fastcall TfrmDocsEdit::dcbDocTypeCloseUp(TObject *Sender) {
 dynamic_cast<TDBLookupComboBox*>(Sender)->DataSource->DataSet->Post();
}


Не подходит:
1. Данные не должны быть отправлены на сервер - набор данных должен стать "DataSource->DataSet->Modified == true"
2. Получаем исключение "...: Dataset not in edit or insert mode" при попытке использовать этот подход для "TDBCheckBox"
Код

void __fastcall TfrmDocsEdit::dcbDocIsActiveClick(TObject *Sender) {
  dynamic_cast<TDBCheckBox*>(Sender)->DataSource->DataSet->Post();
}

И эта ошибка вполне ожидаема т.к. клик по объекту TDBCheckBox не вызывает изменения в связаном DataSet, что и является проблеммой, которую нужно обойти.

Автор: _Dimon_ 16.12.2010, 19:50
Код

 TDataSet * data = dynamic_cast<TDBCheckBox*>(Sender)->DataSource->DataSet;

 if (data->State!=dsBrowse)  data->UpdateRecord();



Незнаю почему, но первый клик не отображает замены, а потом нормально .... надо еще подумать .....


З.Ы. Перед тем как щелкать чекбокс ты вызываеш Edit() ?

Автор: ZVano 17.12.2010, 10:37
Перед щелчком  Edit() не вызываю. Он происходит автоматически.

Приатачиваю тестовый проект, который скидывает в лог все события и состояние DataSet.
Нужно заставить кнопку "bnTbl1Save" быть активной после клика по DBCheckBox.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)