Firemonkey: TGrid usage on Embarcadero C++ Builder XE3

后端 未结 3 472
余生分开走
余生分开走 2021-01-25 04:37

I\'m try to build a tool that reads data from a database and displays it as a table using a TGrid in Firemonkey. I need to use different types of columns like TCheckColumn and T

相关标签:
3条回答
  • 2021-01-25 05:04

    I can't give C++ code but a Delphi example should be easy enough to translate.

    You get and set all cell values the same way, by listening for the OnGetData and OnSetData events, get take/give values of type TValue (XE3 and later). It's just a case of returning the appropriate type in the TValue:

    uses System.RTTI;
    
    procedure Form1.Grid1GetValue(Sender: TObject;const Col, Row: Integer;var Value: TValue);
    begin
      if Col = 1 then
        Value := TValue.From<Integer>(1)
      else if Col = 2 then
        Value := TValue.From<String>('Hello')
      else if Col = 3 then
        Value := Tvalue.From<Single>(1.0);
    end;
    
    procedure Form1.Grid1SetValue(Sender: TObject;const Col, Row: Integer;const Value: TValue);
    begin
      if Col = 1 then
        I := Value.As<Integer>
      else if Col = 2 then
        St := Value.As<String>
      else if Col = 3 then
        Si := Value.As<Single>;
    end;
    

    As far as I can tell a popup menu can't accept or give data.

    0 讨论(0)
  • 2021-01-25 05:09

    TGris does not store any data, you should create your own datastorage.

    Example: TGrid with TCheckColumn, TStringColumn and TPopupColumn

    type
      TField = record
        Checked:  Boolean;
        Name:     string;
        Column:   Byte;
      end;
    
    var
      Fields: TList<TField>;
    
    function SetField(const AChecked: Boolean; const AName: string; const AColumn: Byte): TField;
    begin
      with Result do begin
        Checked := AChecked;
        Name    := AName;
        Column  := AColumn;
      end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      I: Integer;
    begin
      Fields := TList<TField>.Create;
      Fields.Add(SetField(True, 'Name', 1));
      Fields.Add(SetField(True, 'Login', 2));
      Fields.Add(SetField(True, 'Password', 3));
      for I := 1 to Fields.Count do
        PopupColumn1.Items.Add('Column ' + IntToStr(I));
      gdFields.RowCount := Fields.Count;
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      Fields.Free;
    end;
    
    procedure TFormExport.gdFieldsGetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
    begin
      case gdFields.Columns[Col].TabOrder of
        0:  Value := Fields[Row].Checked;
        1:  Value := Fields[Row].Name;
        2:  Value := Fields[Row].Column - 1;
      end;
    end;
    
    procedure TFormExport.gdFieldsSetValue(Sender: TObject; const Col, Row: Integer; const Value: TValue);
    var
      FRec: TField;
    begin
      FRec := Fields[Row];
      case gdFields.Columns[Col].TabOrder of
        0:  FRec.Checked := Value.AsBoolean;
        1:  FRec.Name    := Value.AsString;
        2:  FRec.Column  := Value.AsInteger + 1;
      end;
      Fields[Row] := FRec;
    end;
    

    Now all data from your datastorage will be changed after editing your TGrid, but possible bug in TGrid - never received OnSetValue after changing PopupColumn

    0 讨论(0)
  • 2021-01-25 05:22

    In order to solve your problem, redefine the TCheckCell class in the following way:

    #include <FMX.Grid.hpp>
    #include <boost/dynamic_bitset.hpp>
    
    class CheckCellClass:public TCheckCell
    {
    public:
     __fastcall virtual CheckCellClass(System::Classes::TComponent*AOwner):TCheckCell(AOwner)
     {
     };
    
     virtual System::Rtti::TValue __fastcall GetData(void)
     {
      return TValue::From<bool>(this->IsChecked);
     };
    
     virtual void __fastcall SetData(const TValue&Value)
     {
      TValue V(Value);
      this->IsChecked=V.AsBoolean();
     };
    };
    
    //Redifine TCheckColumn class
    class CheckColumnClass:public TCheckColumn
    {
    private:
     virtual Fmx::Controls::TStyledControl*__fastcall CreateCellControl(void)
     {
      CheckCellClass*Cell=new CheckCellClass(this);
      Cell->OnChange     =&(this->DoCheckChanged);
      return Cell;
     };
    
    public:
    __fastcall CheckColumnClass(System::Classes::TComponent*AOwner):TCheckColumn(AOwner)
     {
     };
    };
    
    //global Data for Save curent State Cell
    
    boost::dynamic_bitset<unsigned char>FullDiscreteInputs;
    
    Add To Grid In Constuctor
     FullDiscreteInputs.resize(100);
     DiscreteInputsGrid->RowCount=FullDiscreteInputs.size();    
     CheckColumnClass* DiscreteInPutsCheckColumn        =new CheckColumnClass(DiscreteInputsGrid);
     DiscreteInputsGrid->AddObject(CoilsCheckColumn);
    
    void __fastcall TForm1::DiscreteInputsGridGetValue(TObject*Sender, const int Col, const int Row,TValue&Value)
    {
     //...
    
     if(DiscreteInputsGrid->ColumnByIndex(Col)==DiscreteInPutsCheckColumn)
     {
     Value=TValue::From<bool>(FullDiscreteInputs[Row]);
     }
     //...
    }
    
    //---------------------------------------------------------------------------
    void __fastcall TForm1::DiscreteInputsGridSetValue(TObject*Sender, const int Col, const int Row, const TValue&Value)
    {
     TValue V(Value);
     if(DiscreteInputsGrid->ColumnByIndex(Col)==DiscreteInPutsCheckColumn)
     {
     FullDiscreteInputs[Row]=V.AsBoolean();
     }
    }
    //---------------------------------------------------------------------------
    
    0 讨论(0)
提交回复
热议问题