0

I made a very simple testproject in Delphi 10.2 using FMX. The setup is simple :

  • TGrid that is binded to a TClientDataSet (done in the designer).
  • button that allows the user to open an XML file

This all works fine and the TGrid is populated with all records from the XML File. The XML file is created by another TClientDataSet from an older project.

Now for the problem.
When I move a column to another position all the data is messed up. I do this by just holding down the mouse on a column and than drag it a few columns to the right.
At first it looks fine, but when you start scrolling vertical, it seems that the data is not in the correct columns anymore.
I have the feeling that it only corrects the data in the visual part of the grid, and as soon as you start scrolling the data is not in the correct columns anymore.

Is this a known bug or is there something wrong with my project.
As I said before, there is absolutely no code in this project all is done in the designer. (except for the clientdataset1.LoadFromFile offcourse)

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
GuidoG
  • 11,359
  • 6
  • 44
  • 79
  • When it comes to FMX, it is important to indicate the Delphi version correctly due to the many changes during the past years. In your text you speak about *XE 10* , which doesn't exist. In the tags you have selected `delphi-xe` which did not have FMX. So please, edit your q and make necessary corrections. – Tom Brunberg Apr 18 '17 at 09:23
  • @TomBrunberg I dont have that delphi here so I cannot check right now which version. But it was XE10 what I saw when starting it. So I am confused here. – GuidoG Apr 18 '17 at 09:29
  • @TomBrunberg I called my colleage whith this delphi it seems to be XE10.2 – GuidoG Apr 18 '17 at 09:32
  • I corrected it for you, there's no 'XE' anymore. Regarding your issue, I was able to reproduce it, but I have no fix and sofar did not find anything on Embarcaderos issue list. – Tom Brunberg Apr 18 '17 at 10:07
  • @TomBrunberg Well I am glad it is reproducable. That means I can report it to embarcadero and hopefully they will make a fix soon – GuidoG Apr 18 '17 at 10:25
  • 1
    Take a look at this question from a few days ago: http://stackoverflow.com/q/43418528/2292722 The problem is the same, but the answer is unnecessarily complicated by the saving/loading of column order. To Get and Set data, the cure is to assign the `Tag` property to the original column and use that as reference instead of the `ACol` parameter. – Tom Brunberg Apr 18 '17 at 10:29
  • @TomBrunberg In my case the columns are not know on formcreate. Since the user can load any xml (created with tclientdataset) the columns can be completely different every time. So I would need to do this after loading the xml file, and in the columnmoved event again somehow ? – GuidoG Apr 18 '17 at 10:45
  • Would it not be enough to set the `tag` property of the columns right after the xml is loaded, then just use e.g. `Value := arr[(Sender as TGrid).Columns[ACol].Tag, ARow];` (here the data is in a 2-dim array) in the `GetValue` and corresponding in `SetValue`. – Tom Brunberg Apr 18 '17 at 10:48
  • @TomBrunberg I dont understand it yet. Currently the grid is populated using livebinding and clientdataset1.loadfromfile(). Should I populate it different to be able to use this ? – GuidoG Apr 18 '17 at 10:57
  • Sorry Guido, I overlooked that you used binding. My suggestion is based on usage of the `OngetValue` and `OnSetValue` events, so doesn't help. – Tom Brunberg Apr 18 '17 at 11:44
  • @TomBrunberg OK but thanks anyway for your time and effort – GuidoG Apr 18 '17 at 11:45
  • @TomBrunberg I found a workaround and posted it here as an answer. – GuidoG Apr 19 '17 at 08:46

2 Answers2

2

This fixed it for me. I just move the fields that where moved in the grid also in the ClientDataSet and thus far it seems to work.

procedure TForm1.Grid1ColumnMoved(Column: TColumn; FromIndex, ToIndex: Integer);
var
  FieldFrom : string;
  FieldTo   : string;
begin
  FieldFrom := Grid1.ColumnByIndex(FromIndex).Header;
  FieldTo   := Grid1.ColumnByIndex(ToIndex).Header;

  ClientDataSet1.FieldByName(FieldFrom).Index := FromIndex;
  ClientDataSet1.FieldByName(FieldTo).Index   := ToIndex;
end;

But I just wish there was a better way of knowing from the TColumn which fieldname is involved. Seems like the most significant information is missing from this class.

GuidoG
  • 11,359
  • 6
  • 44
  • 79
1

You can try populate your data manually (Grid: TGrid; CDS: TClientDataSet):

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  Col: TColumn;
begin
  CDS.Active := True;
  for I := 0 to CDS.FieldDefs.Count - 1 do begin
    Col := TColumn.Create(Grid);
    Grid.AddObject(Col);
    Col.Header := CDS.FieldDefs[I].Name;
    Col.Tag := I;
  end;
  Grid.RowCount := CDS.RecordCount;
end;

procedure TForm1.GridGetValue(Sender: TObject; const ACol, ARow: Integer; var Value: TValue);
begin
  CDS.First;
  CDS.MoveBy(ARow);
  Value := CDS.Fields[ACol].Text;
end;

And after this you can use my solution for columns: stackoverflow.com/q/43418528/2292722

Community
  • 1
  • 1
Alex Egorov
  • 907
  • 7
  • 26
  • Your solution will work but I found a way to fix it and keep using binding so I will stick to that. Thanks – GuidoG Apr 18 '17 at 18:02