How can I set/get property value through RTTI for complex things like TStringGrid.Cells?

delphi, rtti

Solution

Here's the simplest example I can think off to get and set the values from a string grid using RTTI:

var
  ctx: TRttiContext;
  rttitype: TRttiType;
  rttiprop: TRttiIndexedProperty;
  value: TValue;
....
rttitype := ctx.GetType(StringGrid1.ClassType);
rttiprop := rttitype.GetIndexedProperty('Cells');
value := rttiprop.GetValue(StringGrid1, [1, 1]);
rttiprop.SetValue(StringGrid1, [1, 1], value.ToString + ' hello');

I excised the error checking for the sake of simplicity. I'm going to assume that you already know how to check for errors.

Problem

I have values stored in xml and lua code and accessing object's properties through RTTI. ``` var o, v: TValue; // o is current object a: TStringDynArray; // params as array ctx: TRttiContext; tt: TRttiType; p: TRttiProperty; pt: PTypeInfo; begin ... ctx := TRttiContext.Create; try o := GetLastClassInParams(ctx, obj, a, param_idx); tt := ctx.GetType(o.TypeInfo); if high(a) < param_idx then raise Exception.Create(S_FN + S_NOP); p := tt.GetProperty(a[param_idx]); if p = nil then raise Exception.Create(S_FN + S_PNE + a[param_idx]); pt := p.PropertyType.Handle; case p.PropertyType.TypeKind of tkInteger: v := TValue.From<integer>(integer(Value)); tkEnumeration: v := TValue.FromOrdinal(pt, GetEnumValue(pt, VarToStr(Value))); tkUString: v := TValue.From<string>(VarToStr(Value)); tkFloat: v := TValue.From<double>(double(Value)); tkSet: begin temp_int := StringToSet(pt, VarToStr(Value)); TValue.Make(@temp_int, pt, v); end; else v := TValue.FromVariant(Value); end; p.SetValue(o.AsObject, v); ``` I can work with many properties like `Width`, `Lines.Text` of TMemo etc, even with `Panels[0].Width` of TStatusBar (where Panels is TCollection descendant), but thing like `TStringGrid.Cells[x, y]` is something I can't solve. There is help on Embarcadero and some functions like `GetIndexedProperty` (maybe that is what I need), but explanation there as good as `"Gets Indexed Property"`. How to set and get `TStringGrid.Cells[x,y]` through RTTI at runtime if I have values stored as strings like `"Cells[1,1]"`?

Original source