Компонент в ячейке редактирования
Отвлечемся на некоторое время от заголовков TDBGrid и обратимся к редактированию данных. Стандартный внутренний редактор ячеек грида (TInplaceEditor) не всегда самый удобный вариант. Можно использовать собственные диалоговые окна для выбора значений и их редактирования, а можно просто встроить нужный компонент в сам грид. Вот этим мы сейчас и займемся.
Подмена стандартного Inplace-Editor'a в DBGrid отдельным компонентом на примере TDBComboBox.
Для того, чтобы вместо стандартного редактора в колонке DBGrid'а появился другой компонент, проделаем несколько действий:
Создадим отдельный компонент, который будет редактором (в примере используется TDBComboBox). При его создании следует установить свойство Visible в False, для того, чтобы вне грида он не отображался. Компонент DBComboBox выбран для того, чтобы обеспечить автоматическую связь с данными в DataSet'е, который отображается в Grid'е.
При создании компонента, свяжем его с тем же набором данных, что и Grid, в качестве DataField установим имя того поля, редактор которого в гриде мы хотим подменять. Вместо создания вручную компонент можно положить на форму в design-time
FEditor := TDBComboBox.Create(Self); FEditor.Parent := Self; FEditor.Visible := false; FEditor.Style := csDropdownList; FEditor.DataSource := DBGrid.DataSource; FEditor.DataField := 'STATE';
В данном примере список ComboBox'а заполняется значениями из Picklist нужного столбца грида.
for I:=0 to Pred(DBGrid.Columns.Count) do if DBGrid.Columns[I].Field.FieldName = FEditor.DataField then begin { Присвоение списка PickList списку строк ComboBox'a } FEditor.Items.Assign(DBGrid.Columns[I].PickList); Break; end;
Показывать этот компонент мы будем в обработчике события OnDrawColumnCell, когда нужная колонка получает фокус (рис. 2).
procedure TForm1.DBGridDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); begin if (gdFocused in State) then if (Column.Field.FieldName = FEditor.DataField) then begin { Вместо стандартного InplaceEditor'а показываем ComboBox } FEditor.Left := Rect.Left + DBGrid.Left; FEditor.Top := Rect.Top + DBGrid.top; FEditor.Width := Rect.Right - Rect.Left + 2; FEditor.Visible := True; end; end;
Для того, чтобы нарисованный компонент не оставался видимым после того, как нужная ячейка потеряет фокус, спрячем его в обработчике события ColExit
procedure TForm1.DBGridColExit(Sender: TObject); begin { При выходе с поля ComboBox надо скрыть } if DBGrid.SelectedField.FieldName = FEditor.DataField then FEditor.Visible := false; end;
Для того, чтобы менять значение поля можно было не только выбором мышью из списка, но и с клавиатуры, необходимо передавать ComboBox'у нажатия клавиш DBGrid'а, при редактировании поля. Это можно сделать как в обработчике события OnKeyPress DBGrid'a, так и в обработчике OnKeyDown. Я приведу пример обработчика OnKeyPress.
procedure TForm1.DBGridKeyPress(Sender: TObject; var Key: Char); begin { Передаем все нажатия клавиш в InplaceEditor'е созданному ComboBox'у } if (Key <> chr(9)) then if (DBGrid.SelectedField.FieldName = FEditor.DataField) then begin FEditor.SetFocus; SendMessage(FEditor.Handle, WM_CHAR, word(Key), 0); end; end;
В примере использован TDBComboBox, по аналогии с ним можно использовать для редактирования и другие компоненты. Ниже на рисунке показан пример, где аналогичным образом в грид встроен TDBDateEdit для редактирования полей типа "дата":
1 2 3 4 5 6
8 8 8
| |