TStringGrid 很简单,只需使用 Cells 数组写入和读取数据
StringGrid1.Cells[0,1] := 'Hello World';
ShowMessage(StringGrid1.Cells[0,2]);
对于 TGrid,您需要挂钩 OnGetValue 和 OnSetValue 事件。由于这些在滚动网格时会重复调用,因此您可能希望在本地缓存数据。以下来自我的网站http://monkeystyler.com/guide/TGrid
设置和获取单元格数据
TGrid 内部不存储任何数据。您可以设置单元格数据并将其读回,但每个网格仅创建在给定当前控件大小和行高的情况下显示它们所需的最小单元格数量。当网格滚动时,单元格将被回收,您需要将新数据设置到这些回收的单元格中。
当需要更新单元格的显示时,TGrid 实际上会通过 OnGetValue 事件按需获取数据。 OnGetValue 传入需要其数据的单元格的行和列,并期望返回包含数据的 TValue 记录。
在 System.RTTI 单元中声明的 TValue 是可以存储任何类型数据的记录,类似于 Variant,只是它是类型安全的,并且尝试读取错误类型的数据会导致访问违反。由于 TValue 是一条记录,因此无需“释放”它。
TValue 使用泛型来指定要读取或写入的数据类型。下面的示例显示了为每种内置单元格类型设置数据的示例,
procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer;
var Value: TValue);
begin
if Col = 0 then
//TTextCell
Value := TValue.From<String>(IntToStr(Row))
else if Col = 1 then
//TCheckCell
Value := TValue.From<Boolean>((Row mod 2) = 0)
else if Col = 2 then
//TProgressCell
Value := TValue.From<Single>(Row)
else if Col = 3 then
//TPopupColumn
// - doesn't accept data
else if Col = 4 then
//TImageColumn
Value := TValue.From<TBitmap>(ImageControl1.Bitmap);
//Or Value := TValue.From<String>('C:/Pictures/Kitten.png');
end;
网格将 TValue 传递给单元格控件的 SetData 方法(由 TControl 引入),因此要传入的数据类型将取决于该方法接受的内容。除了“正确”类型(例如,TProgressBar 的单一类型)之外,许多 SetData 方法都会解析出字符串值,例如上面的 TImageControl 示例,将文件名作为字符串。
OnSetValue
当单元格中的数据发生更改时,将调用 OnSetValue 事件,再次使用列和行以及包含数据的 TValue。该示例再次展示了如何接受所有内置列类型的数据。
procedure TForm1.Grid1SetValue(Sender: TObject;const Col, Row: Integer;var Value: TValue);
var AString: String;
ABoolean: Boolean;
ASingle: Single;
begin
if Col = 0 then
//TTextCell
AString := Value.AsType<String>
else if Col = 1 then
//TCheckCell
ABoolean := Value.AsType<Boolean>
else if Col = 2 then
//TProgressCell
ASingle := Value.AsType<Single>
else if Col = 3 then
//TPopupColumn
// - doesn't send data
else if Col = 4 then
//TImageColumn
// - doesn't send data
;
end;
重申一下,因为 TValue 是类型检查的,所以只能提取它包含的数据类型。如果您希望将进度单元格的值作为字符串,
AString := Value.As<string>;
将导致访问冲突。相反,您必须将数据提取为浮点数并使用例如 FloatToStr (SysUtils) 进行转换。