When data has no ready-made source, a StiUserData component supplies values on demand through an event — useful for reflection results, computed rows or live objects.

Register the user data. Tell the report how many rows to expect:
stiReport1.RegData("HatchStyleEnum", Enum.GetNames(typeof(HatchStyle)));

assemblys = typeof(Graphics).GetMethods();
stiUserData1.Count = assemblys.Length;
stiReport1.RegData("UserData", stiUserData1);
Serve each cell. The engine raises GetData for every column and row position:
private void stiUserData1_GetData(object sender, StiUserGetDataEventArgs e)
{
    if (e.ColumnName == "Name")       e.Data = assemblys[e.Position].Name;
    if (e.ColumnName == "ReturnType") e.Data = assemblys[e.Position].ReturnType.Name;
    if (e.ColumnName == "IsStatic")   e.Data = assemblys[e.Position].IsStatic;
}

How it works. The report pulls values only as it renders, so a virtual data source of any size can be fed row-by-row without materializing it up front.
На скриншоте ниже Вы можете увидеть результат выполнения данного кода:

Using User Data in Reports