Kotъ-Begemotъ, спасибо большое за подробное объяснение. С воодушевлением принялся за воплощение вашей идеи. И когда сделал так, как вы описали, появилась даже мысль разработать собственный компонент. Поэтому начал разбираться как делаются компоненты, просматривать исходники. В исходнах компонента
DBLookupComboboxEh обратил внимание на свойство
Style. И оказалось, что если выставить Style равным
csDropDownEh (по умолчанию стоит csDropDownListEh), то в поле ввода можно
вводить такие значение, которых ещё нет в справочнике. А это как раз мне было и нужно!
Итак, если вы хотите обеспечить максимум комфорта пользователям при добавлении данных в базу, рекомендую следующее.
Во-первых и самое главное – использоватать обязательно компонент DBLookupComboboxEh (данных компонент входит в библиотеку Еhlib, которая для «нашего брата» бесплатна). Далее в свойствах этого компонента установите следующее:
DataSource – источник данных главной таблицы
DataField– поле внешнего ключа, ссылающегося на справочник, в главной таблице
ListSource – источник данных справочника
KeyField – поле первичного ключа в справочнике
ListField – поле, значение которого будут показываться в выпадающем списке.
Style = csDropDownEh. (в этом случае появляется возможность вводить в поле ввода такие значения, которых нет в справочнике);
DropDownBox->AutoDrop = true. (по мере ввода данных автоматически будет появляться выпадающий список).
А теперь исходники:
Код: Выделить всё
procedure TfMain.lcbEhChange(Sender: TObject);
var
s: string;
begin
with TDBLookupComboboxEh(Sender) do begin
if Tag = 0 then
exit;
s := Copy (Text, 0, SelStart);
//фильтруем
ListSource.DataSet.Filtered := false;
ListSource.DataSet.Filter := ListField + ' LIKE ''' + s + '%''';
ListSource.DataSet.Filtered := true;
Tag := 0;
end;
end;
procedure TfMain.lcbEhExit(Sender: TObject);
var
s: string;
begin
with TDBLookupComboboxEh(Sender) do begin
// если введенного текста нет в справочнике, то добавляем
if (Text<> ListSource.DataSet.FieldByName(ListField).AsString)
and (Text <> '') then
// но сначала спросим у пользователя
if Application.MessageBox(pChar('Вы действительно хотите' +
'добавить в справочник "'+ Hint+'" запись "'+Text+'"?'),
'Подтверждение', MB_ICONINFORMATION + MB_OKCANCEL) = id_ok then
begin
// добавляем в справочник
ListSource.DataSet.Insert;
ListSource.DataSet.FieldByName(ListField).AsString := Text;
ListSource.DataSet.Post;
s := Text;
ListSource.DataSet.Close;
ListSource.DataSet.Open;
// а затем в основную таблицу
ListSource.DataSet.Locate(ListField, s, [loCaseInsensitive]);
DataSource.DataSet.FieldByName(DataField).AsInteger :=
ListSource.DataSet.FieldByName(KeyField).AsInteger;
end;
// отмена фильтрации в справочнике
ListSource.DataSet.Filtered := false;
ListSource.DataSet.Filter := '';
ListSource.DataSet.Filtered := true;
end;
end;
procedure TfMain.lcbEhKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
with TDBLookupComboboxEh(Sender) do begin
if Char(key) = #13 then begin
DataSource.DataSet.FieldByName(DataField).AsString :=
ListSource.DataSet.FieldByName(KeyField).AsString;
SelectNext(Sender as TWinControl, True, True);
end;
end;
end;
procedure TfMain.lcbEhKeyPress(Sender: TObject; var Key: Char);
begin
TDBLookupComboboxEh(Sender).Tag := 1;
//Чтобы не было лишнего звука при нажатии на Enter
if Key = #13 then
Key := #0;
end;
Я думаю ясно, что событию OnChange нужно назначить процедуру lcbEhChange, OnKeyDown lcbEhKeyDown и т.д.
Приведу небольшие комментарии.
Фильтрацию данных по мере ввода текста пользователем реализуем в событии
OnChange (процедура
lcbEhChange). Было замечено, что в некоторых случаях событие OnChange у компонента DBLookupComboboxEh срабатывает несколько раз подряд, поэтому в lcbEhKeyDown свойству Tag компонента присваиваем 1, а в конце процедуры lcbEhChange это свойство делаем равным 0;
Процедуры
lcbEhKeyDown и
lcbEhKeyPress необходимы для того, чтобы при выборе из выпадающего списка каких-либо значений с помощью клавиш стрелка вверх/вниз и нажатии на Enter осуществлялся переход к следующему компоненту. Пришлось использовать процедуру
OnKeyDown, т.к. при выборе нажатием на Enter значений из списка, в событие
OnKeyPress невозможно перехватить нажатие на Enter (компонент в этом случае при нажатии на Enter присваивает переменной Key код клавиши 0).
Ну и соответственно в
OnExit проверяем, было ли введено значение, которого нет в справочнике.
В конце замечу, что описанное выше
идеально подходит для простых справочников, т.е. в которых всего два поля - первичный ключ и какое-либо значение. Если имеем дела со справочниками, у которых несколько полей, то без кнопочки, вызывающей форму для редактирования, тут уж не обойтись.
EhLib супер! =D>