i want to have a combobox in a column of the fncdatagrid.
This combobox should fill with the distinct Text-Values of this column.
if i edit this column i want to input a new text in the field or choose a text from the combobox, and then post this value to the underlying Database.
The grid is bound to a datasource with the gridDatabaseAdapter.
Is there a easy way to fill the combobox in the Datagrid?
For inserting the combobox i use the GridKosten.Columns[3].Editor:=getComboEdit;
Thank you for the Code, but with this i dont get a combobox in Column 3 or any other column.
There is only a normal editField.
And what is the ```
TMSFNCDataGrid1.Columns[2].AddSetting(gcsEditor);
for.
The 3,4 and 5 Column should be a ComboField at the End.
if (ACell.Column = 3) and (AInplaceEditor is TTMSFNCDataGridComboEdit) then
is not true at any time
// Nachdem das Grid gezeichnet wurde
procedure TfrmKosten.grdKostenAfterDrawGrid(Sender: TObject; AGraphics: TTMSFNCGraphics; ARect: TRectF);
Var
lUmsatz,lKosten: Double;
begin
// Summe der Kosten Spalte RechBetrag in edtSumKosten eintragen
lKosten:=grdKosten.ColumnSum(5);
edtSumKosten.Text := FormatFloat('#,##0.00', lKosten) + ' €';
// Summe der Rechnungsbeträge aus der Rechnungstabelle zusammenrechnen und in edtUmsatz schreiben
DM.q1.sql.Clear;
DM.q1.sql.Text := 'Select Sum(RBetrag) As Umsatz from Rechnungen ' + lWhere;
DM.q1.Open;
lUmsatz := DM.q1.FieldByName('Umsatz').AsFloat;
DM.q1.Close;
edtSumUmsatz.Text := FormatFloat('#,##0.00', lUmsatz) + ' €';
// Differenz zwischen Umsatz und Kosten = Gewinn in edtSumGewinn eintragen
edtGewinn.Text := FormatFloat('#,##0.00', lUmsatz-lKosten) + ' €';
end;
procedure TfrmKosten.grdKostenGetCellFormatting(Sender: TObject; ACell: TTMSFNCDataGridCellCoord; AData: TTMSFNCDataGridCellValue; var AFormatting: TTMSFNCDataGridDataFormatting;
var AConvertSettings: TFormatSettings; var ACanFormat: Boolean);
begin
if ACell.Row > 0 then
begin
if ACell.Column = 5 then
begin
ACanFormat := True;
AFormatting.&Type := gdftFloat;
AFormatting.Format := '0.00';
end;
end;
end;
procedure TfrmKosten.grdKostenGetCellLayout(Sender: TObject; ACell: TTMSFNCDataGridCell);
begin
if ACell.Row > 0 then
if ACell.Column in [0, 1, 5, 6] then
ACell.Layout.TextAlign := gtaTrailing; // RechtsbĂĽndige Ausrichtung
end;
procedure TfrmKosten.grdKostenGetInplaceEditorProperties(Sender: TObject; ACell: TTMSFNCDataGridCellCoord;
AInplaceEditor: TTMSFNCDataGridInplaceEditor; AInplaceEditorType: TTMSFNCDataGridInplaceEditorType);
var
cbo: TTMSFNCDataGridComboEdit;
sl: TStringList;
begin
if (ACell.Column in [2,3,4]) and (AInplaceEditor is TTMSFNCDataGridComboEdit) then
begin
cbo := (AInplaceEditor as TTMSFNCDataGridComboEdit);
sl := TStringList.Create;
try
sl.Duplicates := TDuplicates.dupIgnore;
sl.Sorted := True;
GridDatabaseAdapterKo.LoadValuesFromField(GridDatabaseAdapterKo.FieldAtColumn[ACell.Column], sl);
cbo.Items.Assign(sl);
finally
sl.Free;
end;
end;
end;
procedure TfrmKosten.GridDatabaseAdapterKoDataToField(Sender: TObject;
ACell: TTMSFNCDataGridCellCoord; AMasterField, AField: TField;
AInplaceEditor: TTMSFNCDataGridInplaceEditor;
ACellValue: TTMSFNCDataGridCellValue; var Handled: Boolean);
var
cbo: TTMSFNCDataGridComboEdit;
begin
if (ACell.Column = 3) and (AInplaceEditor is TTMSFNCDataGridComboEdit) then
begin
cbo := (AInplaceEditor as TTMSFNCDataGridComboEdit);
AField.AsString := cbo.Text;
Handled := True;
end;
end;
Some Problems appear at work:
When the user cklick to a combofield, this is empty and when he click to an other field the data in the previos field is cleared and this emty field is saved.
One solution is to fill the Combofield.text with the data from the datarecordfield of this Column.
(Where do I enter this in previous code)
An other way is to only allow the user to use this feature if i make a new data record with a button NewDataRecord.
So how to activate this function only when i append a new datarecord, and deactivate it in normal readonly mode of the grid?
Whe connected to a dataset, it will always try to save the value of the field when navigating to another record when that record is in edit mode. Edit mode starts when editing a cell. So you can block editing mode with the OnCanEditCell event. You can indeed try to fill the value of the combobox before starting which can be done in the OnCellEditGetData. If the value is empty, you can prefill it to something else.
Thank you for your Help.
I set a Global Var GridEditMode to False at FormCreate.
With a Button "Insert" i append a NewLine and set the GridEditMode to True and then let the user edit the new line with 3 Columns.
Now the Problem:
in what event can i set the GridEditMode to False, so that the user cant edit in the Grid after editing the new line.
That is possible because there are 6 Fields in one Row to change and every Field will do a post.
So i dont know whether the Customer is ready with the DataRow to change;
For the Moment i use a Button "AddRow" and change its caption to "Save" so the user have to press save if he is ready.
At AddRow i set EdtitMode of the Grid to True, When Save is Pressed i set the EditMode of the Grid to False. So the user should only in editMode when insert new Data.
But if he dont press the save Button than the EditMode still is on.
The only thing that could help where a RowChange Event, but if we are in the last row and end the input there is no new Row i think and therefor no RowChange.
i cannot use AfterPost of the query to set editMode to false because it fires at the append row and then i cannot change anything in the new row. Also if i change a field in the row it will fire and i cannot edit the next field.
How are you adding a row? directly by using Append on dataset level? If so, isn't it sufficient to check the dataset state? Shouldn't it be in insert or append mode?
// ****************************************************************************
// * Neuen datensatz hinzufĂĽgen *
// ****************************************************************************
procedure TfrmKosten.KostenAddLine;
begin
if GridEditMode then
begin
GridEditMode := False; // EditMode wieder ausschalten da hinzufĂĽgen abgeschlossen ist
btnAdd.Caption:='HinzufĂĽgen';
end
else
begin
GridEditMode := True;
btnAdd.Caption:='Speichern';
// Neuen datensatz in Kosten anlegen und vorbelegen
grdKosten.Options.Editing.Enabled := True;
DM.qKosten.Append;
DM.qKosten.FieldByName('RechDatum').AsDateTime := Date;
DM.qKosten.FieldByName('ZahlDatum').AsDateTime := Date;
DM.qKosten.FieldByName('RechBetrag').AsFloat := 0;
// DM.qKosten.FieldByName('USt').AsFloat := StrToInt(edtEMwst.Text);
DM.qKosten.FieldByName('Bar').AsBoolean := False;
// Nächste Belegnummer für KostenBeleg berechnen und eintragen
DM.q1.sql.Clear;
DM.q1.sql.Text := 'Select Max(BelegNr) As MaxBelegNr from Kosten';
DM.q1.Open;
// Neue BelegNr in Datensatz einfĂĽgen
DM.qKosten.FieldByName('BelegNr').AsInteger := DM.q1.FieldByName('MaxBelegNr').AsInteger + 1;
DM.q1.Close;
// Datensatz speichern in DB
DM.qKosten.Post;
Var x:TDatasetState;
x:= DM.qKosten.State; // The DatasetState here is dsBrowse
end;
end;
You might want to track the previous state of the dataset during editing (before the post). If that differs from the actual state you know it has been in insert mode