При работе с компонентом DBGrid в Delphi иногда возникает необходимость использовать выпадающие списки (picklist) для одного или нескольких столбцов. Однако получение выбранного значения из такого списка может вызвать затруднения, особенно если нужно получить значение до его сохранения в ячейке сетки. В этой статье мы рассмотрим несколько способов решения этой задачи.
Понимание проблемы
Компонент DBGrid позволяет добавлять выпадающие списки к столбцам через свойство PickList объекта TColumn. Этот список представляет собой обычный TStrings, но у него нет прямого свойства для получения выбранного значения, как у комбинированного списка (TComboBox).
Как отмечал пользователь Hansvb в исходном обсуждении, у нас есть два варианта:
1. Получить значение по индексу (ValueFromIndex[i])
2. Получить индекс по тексту (IndexOf('some text'))
Но оба способа требуют заранее знать либо индекс, либо текст, что создает проблему "курицы и яйца".
Решение 1: Использование событий DBGrid
Один из способов получить выбранное значение - использовать события DBGrid. Например, можно обработать событие OnColEnter или OnDrawColumnCell:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if (gdFocused in State) and (Column.PickList.Count > 0) then
begin
// Здесь можно получить доступ к PickList текущего столбца
ShowMessage('Выбранный индекс: ' + IntToStr(Column.PickList.IndexOf(Column.Field.AsString)));
end;
end;
Решение 2: Подмена редактора столбца
Более гибкий способ - создать собственный редактор для столбца на основе TComboBox:
type
TMyDBGrid = class(TDBGrid)
private
FCombo: TComboBox;
FColIndex: Integer;
protected
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
constructor TMyDBGrid.Create(AOwner: TComponent);
begin
inherited;
FCombo := TComboBox.Create(Self);
FCombo.Visible := False;
FCombo.Parent := Self;
FCombo.OnChange := ComboChange;
end;
procedure TMyDBGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
begin
if (ARow = Row) and (ACol = Col) and (Columns[ACol].PickList.Count > 0) then
begin
FColIndex := ACol;
FCombo.Items := Columns[ACol].PickList;
FCombo.ItemIndex := FCombo.Items.IndexOf(Columns[ACol].Field.AsString);
FCombo.Left := ARect.Left + Left;
FCombo.Top := ARect.Top + Top;
FCombo.Width := ARect.Right - ARect.Left;
FCombo.Height := ARect.Bottom - ARect.Top;
FCombo.Visible := True;
end
else
FCombo.Visible := False;
inherited;
end;
procedure TMyDBGrid.ComboChange(Sender: TObject);
begin
if FCombo.ItemIndex >= 0 then
ShowMessage('Выбрано: ' + FCombo.Items[FCombo.ItemIndex]);
end;
Решение 3: Использование DBLookupComboBox
Как предложил Hansvb, альтернативой может быть использование DBLookupComboBox вместо picklist в DBGrid. Это дает больше контроля над выбором значений:
procedure TForm1.SetupLookupCombo;
begin
DBLookupComboBox1.ListSource := DataSource2; // источник данных для списка
DBLookupComboBox1.ListField := 'DisplayField'; // поле для отображения
DBLookupComboBox1.ListFieldIndex := 0;
DBLookupComboBox1.KeyField := 'KeyField'; // ключевое поле
DBLookupComboBox1.DataSource := DataSource1; // основной источник данных
DBLookupComboBox1.DataField := 'FieldToUpdate'; // поле для обновления
end;
Решение 4: Обработка события OnEditButtonClick
Если вы используете стиль столбца cbsAuto, можно обработать событие OnEditButtonClick:
procedure TForm1.DBGrid1EditButtonClick(Sender: TObject);
var
Grid: TDBGrid;
Col: TColumn;
begin
Grid := Sender as TDBGrid;
Col := Grid.Columns[Grid.SelectedIndex];
if Col.PickList.Count > 0 then
begin
// Здесь можно получить текущее значение
ShowMessage('Текущее значение: ' + Col.Field.AsString);
end;
end;
Заключение
Хотя стандартный picklist в DBGrid не предоставляет прямого доступа к выбранному значению, существует несколько способов обойти это ограничение. Выбор метода зависит от конкретных требований вашего приложения:
Для простых случаев подойдет обработка событий DBGrid
Для большего контроля можно создать собственный редактор столбца
DBLookupComboBox предлагает более функциональную альтернативу
Событие OnEditButtonClick позволяет перехватывать выбор значения
Каждый из этих подходов имеет свои преимущества и может быть адаптирован под конкретные нужды разработчика.
Статья описывает методы получения выбранного значения из выпадающего списка в компоненте DBGrid в Delphi.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.