Firemonkey: использование TGrid в Embarcadero C++ Builder XE3

Я пытаюсь создать инструмент, который считывает данные из базы данных и отображает их в виде таблицы, используя TGrid в Firemonkey. Мне нужно использовать разные типы столбцов, такие как TCheckColumn и TPopupColumn, но я не могу найти хорошего руководства или примера того, как их использовать в C++ Builder.

В любом случае, мне удалось понять использование TStringColumn, TProgressColumn, устанавливающего значение ячейки в событии TGrid onGetValue.

Кто-нибудь из вас знает, как установить значение для столбцов типа TCheckColumn, TImageColumn и TPopupColumn?

спасибо Даниэле

---ОБНОВИТЬ---

Мне удалось использовать TProgressColumn. Это то, что я делаю в конструкторе формы:

// TStringColumn
Grid1->AddObject(new TStringColumn(this));
// TCheckColumn
TCheckColumn* c = new TCheckColumn(this);
Grid1->AddObject(c);
// TPopupColumn
// list of values
TStringList * l = new TStringList(NULL);
l->Add(L"First");
l->Add(L"Second");
l->Add(L"Third");
TPopupColumn* p = new TPopupColumn(this);
// adding the list to the PopupColumn
p->Items = l;
Grid1->AddObject(p);
// TProgressColumn
Grid1->AddObject(new TProgressColumn (this));
Grid1->RowCount = 3 ;

и это метод Grid1GetValue:

// TStringColumn
if(Col == 0) Value = TValue::From<String>(Row);
// TCheckColumn  !! Can't make it work
if(Col == 1) Value = TValue::From<Boolean>(true);
// TPopupColumn
if(Col == 2)    Value = TValue::From<int>(2);
// TProgressColumn
if(Col == 3)    Value = TValue::From<double>(50.0);

---ОБНОВИТЬ---

если я сохраняю значение столбца с помощью метода OnSetValue

void __fastcall TForm1::Grid1SetValue(...)
{
if(Col == 1) check = Value;
}

а затем установите его с помощью метода OnGetValue:

void __fastcall TForm1::Grid1GetValue(...)
{
// TCheckColumn  !! Can't make it work
if(Col == 1) Value = check;// TValue::From<Boolean>(true);
}

После того, как я нажму на один флажок, все остальные флажки изменят свое состояние. Итак, компонент работает правильно... теперь дело в том, как правильно установить значение true или false.


person Daniele Pozzobon    schedule 21.03.2013    source источник


Ответы (3)


TGris не хранит никаких данных, вам следует создать собственное хранилище данных.

Пример: TGrid с TCheckColumn, TStringColumn и 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;

Теперь все данные из вашего хранилища данных будут изменены после редактирования вашего TGrid, но возможная ошибка в TGrid - никогда не получал OnSetValue после изменения PopupColumn

person Alex Egorov    schedule 24.09.2013

Я не могу привести код C++, но пример Delphi должен быть достаточно простым для перевода.

Вы получаете и устанавливаете все значения ячеек одинаково, прослушивая события OnGetData и OnSetData, получая значения типа TValue (XE3 и более поздние версии). Это просто случай возврата соответствующего типа в 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;

Насколько я могу судить, всплывающее меню не может принимать или предоставлять данные.

person Mike Sutton    schedule 21.03.2013
comment
На самом деле код очень похож (я разместил свой код в обновлении поста). Вы когда-нибудь использовали TCheckColumn? - person Daniele Pozzobon; 22.03.2013
comment
У вас возникли проблемы с установкой значения или CheckColumn игнорирует установленное вами значение? - person Mike Sutton; 22.03.2013
comment
На самом деле, я только что узнал, что если я сохраняю значение, которое имеет ячейка в методе OnSetValue, а затем назначаю его ячейке в методе OnGetValue, другие строки изменяют его состояния. - person Daniele Pozzobon; 27.03.2013
comment
Вы говорите о сохранении TValue или о том, что вы из него извлекаете? - person Mike Sutton; 27.03.2013

Чтобы решить вашу проблему, переопределите класс TCheckCell следующим образом:

#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();
 }
}
//---------------------------------------------------------------------------
person Pavel    schedule 15.05.2015