CheckBox в DBGrid
Мой вопрос заключается в том, как установить столбец в dbgrid в Delphi 7, который будет с элементами флажка.
Заранее спасибо.
4 ответа
ОК, я использовал эту статью для моей проблемы. ОК Но проблема в том, что это не сработало так, как должно. Поэтому я изменяю свою логику в коде. И реализуя это, сохраняя выбранные строки из dbgrid в списке.
Самый простой и наиболее полный метод, который я тестировал, заключается в следующем:
В приватном разделе вашего устройства объявите глобальный для сохранения параметров сетки. Он будет использоваться для восстановления после временного отключения редактирования текста при входе в столбец флажка - поскольку это, возможно, одна из небольших ошибок, упомянутых Джорданом Борисовиным в отношении статьи delphi.about.com.
private
GridOriginalOptions : TDBGridOptions;
В событии OnCellClick, если поле имеет логическое значение, переключите и опубликуйте изменение в базе данных
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
if (Column.Field.DataType=ftBoolean) then
begin
Column.Grid.DataSource.DataSet.Edit;
Column.Field.Value:= not Column.Field.AsBoolean;
Column.Grid.DataSource.DataSet.Post;
end;
end;
Рисование флажка для логических полей сетки
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
CtrlState: array[Boolean] of integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED) ;
begin
if (Column.Field.DataType=ftBoolean) then
begin
DBGrid1.Canvas.FillRect(Rect) ;
if (VarIsNull(Column.Field.Value)) then
DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_INACTIVE)
else
DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, CtrlState[Column.Field.AsBoolean]);
end;
end;
Теперь в новой части отключите редактирование ячеек, находясь в логическом столбце. В событиях OnColEnter и OnColExit:
procedure TForm1.DBGrid1ColEnter(Sender: TObject);
begin
if Self.DBGrid1.SelectedField.DataType = ftBoolean then
begin
Self.GridOriginalOptions := Self.DBGrid1.Options;
Self.DBGrid1.Options := Self.DBGrid1.Options - [dgEditing];
end;
end;
procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
if Self.DBGrid1.SelectedField.DataType = ftBoolean then
Self.DBGrid1.Options := Self.GridOriginalOptions;
end;
Более того, используйте клавишу пробела для переключения флажка
procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if ((Self.DBGrid1.SelectedField.DataType = ftBoolean) and (key = VK_SPACE)) then
begin
Self.DBGrid1.DataSource.DataSet.Edit;
Self.DBGrid1.SelectedField.Value:= not Self.DBGrid1.SelectedField.AsBoolean;
Self.DBGrid1.DataSource.DataSet.Post;
end;
end;
Это оно!
Прошу прощения за то, что опубликовал это как ответ, у меня пока нет 50 репутации, чтобы добавлять комментарии.
Mihai MATEI очень близок к редкому (как на самом деле работающему) решению, за исключением случая использования, в котором он содержит ошибки.
Всякий раз, когда первое действие пользователя в сетке состоит в том, чтобы щелкнуть по флажку, первый щелчок будет работать, но второй откроет основной редактор DBGrid.
Это происходит потому, что механизм GridOriginalOptionsmechan должен быть инициализирован. Для этого просто добавьте следующий код в событие OnEnter сетки:
procedure TForm1.DBGrid1Enter(Sender: TObject);
begin
DBGrid1ColEnter(Sender);
end;
Это оно!
Если вы используете TClientDataset+TDatasetProvider+TDataset, вы можете манипулировать вариантом массива данных, прежде чем он попадет в набор данных клиента, и включить не обновляемое логическое поле.
После этого все, что вам нужно, это рисовать на сетке, используя событие OnDrawColumnCell. Здесь я не использовал CheckBox, а просто растровое изображение (когда пользователь щелкает, он меняется на выбранный / невыбранный).