TrevorS 3 Posted March 10, 2023 Type THelpModel = Class(TGridModel); procedure TViewPart.ChangeStringGridComboBoxCurrency(Sender: TObject); begin with TComboBox(Sender), StringGridPartDet do begin THelpModel(StringGridPartDet.Columns[2].Model).DoSetValue(Col,Row, TValue.From<String>(Items[ItemIndex]) ); StringGridPartDet.Columns[2].UpdateCell(Row); end; end; procedure TViewPart.StringGridPartDetCreateCustomEditor(Sender: TObject; const Column: TColumn; var Control: TStyledControl); begin if Column = StringGridPartDet.Columns[2] then begin Control := TComboBox.Create(Self); TComboBox(Control).Items.AddStrings(['GBP', 'EUR']); With StringGridPartDet, TComboBox(Control) do ItemIndex := Items.IndexOf(THelpModel(StringGridPartDet.Columns[2].Model).DoGetValue(Col,Row).AsString); TComboBox(Control).OnChange:= ChangeStringGridComboBoxCurrency; end; end; I have a StringGrid (StringGridPartDet) connected to a DataSet, I have used the attached code to update the currency column with a value from a ComboBox, the value appears correctly in the StringGrid, but does not update the DataSet. AmI missing a step? Share this post Link to post
programmerdelphi2k 237 Posted March 10, 2023 (edited) try this... // my sample in FMX project AGridOrStringGrid.BeginUpdate; try TMyHackTGridModel(AGridOrStringGrid.Model).DoSetValue(ACol, ARow, AValue); // calls OnSetValue(...); // AGridOrStringGrid.Model.PostEditorValue; // <---- all rest is done by "Model" if datasource is your table, etc... // finally AGridOrStringGrid.EndUpdate; end; Edited March 10, 2023 by programmerdelphi2k Share this post Link to post
TrevorS 3 Posted March 13, 2023 Thanks for your suggestion, but the behaviour remains the same - the grid updates correctly, but not the data source. Is there a 'conventional' way to add a combobox to a grid (that's connected to a data source)? Share this post Link to post
programmerdelphi2k 237 Posted March 13, 2023 FMX sample: using more easy way to "use a list of values in a column" = PopUpColumn on StringGrid type TForm1 = class(TForm) StringGrid1: TStringGrid; PopupColumn1: TPopupColumn; Memo1: TMemo; procedure StringGrid1CreateCustomEditor(Sender: TObject; const Column: TColumn; var Control: TStyledControl); procedure StringGrid1EditingDone(Sender: TObject; const ACol, ARow: Integer); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.StringGrid1CreateCustomEditor(Sender: TObject; const Column: TColumn; var Control: TStyledControl); begin Memo1.Lines.Add(TimeToStr(now) + ' - CreateCustomEditor'); // // loading values... or anyother sources! PopupColumn1.Items.DelimitedText := 'Item1,Item2,Item3'; end; procedure TForm1.StringGrid1EditingDone(Sender: TObject; const ACol, ARow: Integer); begin Memo1.Lines.Add(TimeToStr(now) + ' - EditingDone'); end; Share this post Link to post
programmerdelphi2k 237 Posted March 13, 2023 (edited) other way is using the "var Control" param on "CreateCustomEditor" event: implementation {$R *.fmx} function fncMyComboBox: TComboBox; // my Control used in my TGrid-CustomEditor... begin // it will be "created"... and "destroyed by Grid" result := TComboBox.Create(nil); // result.Items.AddStrings(['One', 'Two', 'Three']); // result.OnChange := Form1.MyComboBoxChange; end; procedure TForm1.MyComboBoxChange(Sender: TObject); begin if not(Sender is TComboBox) then exit; // try BindSourceDB1.DataSet.Edit; BindSourceDB1.DataSet.FieldByName('MyId').Value := TComboBox(Sender).Selected.Index; BindSourceDB1.DataSet.Post; except // ??? end; end; procedure TForm1.Grid1CreateCustomEditor(Sender: TObject; const Column: TColumn; var Control: TStyledControl); begin if (Column.Index = 0) then Control := fncMyComboBox; // who's the "destroyer" now? end; initialization ReportMemoryLeaksOnShutdown := true; // any memory leaks? end. Edited March 13, 2023 by programmerdelphi2k Share this post Link to post