Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

TLMDGrid - custom data source not being asked for values

I'm using TLMDGrid V2022.9 and C++ Builder 11.3

I'm using the grid with a custom data source that is empty when the application starts. On initial paint the form asks the data source for its row count and it returns 0.

I used this code to add data to my datasource:

//'message' is passed into this function:
CommandResponseGrid->BeginUpdate();
commandGridData->AddRow(Now(), message.message, message.tube);
CommandResponseGrid->DataRowCount = commandGridData->RowCount(); //tried this but it doesn't help...
    CommandResponseGrid->EndUpdate();

After this the grid calls the custom data's RowCount() method, which returns the number of rows. The grid then displays just one an empty row regardless of how many rows I add to the data, but at no time does the grid call the GetDataCell(int Row, int Col) method to fetch the data. I don't understand why this is...

If, on app startup, I return a number greater than 0 from RowCount() the grid does call GetDataCell but, of course, there's no data at that time. It's like initially returning 0 from RowCount() makes the grid decide there never will be any data to fetch?

Do I need to do something else to get the grid to update the data values?

Andy


Comments

  • 6 Comments sorted by Votes Date Added
  • edited August 2023 Posts: 0 Accepted Answer Vote Up0Vote Down
    Try this code:

    type
      TLMDGridHack = class(TLMDGrid);

    procedure TForm17.Button1Click(Sender: TObject);
    begin
      MyGrid.BeginUpdate;
      try
        MyStore.AddRow(...);
        TLMDGridHack(MyGrid).IncludeChange(cfData);
        TLMDGridHack(MyGrid).SyncGridStore;
      finally
        MyGrid.EndUpdate;
      end;
    end;

    Alternatively, you can move all this stuff (BeginUpdate/EndUpdate, IncludeChange and SyncGridStore) directly inside your AddRow method.
  • edited August 2023 Posts: 0Vote Up0Vote Down
    Sorry Eugene, I'm using C++ and my Object Pascal knowledge is not enough to translate your code into it.

    In particular, I'm not sure what this means:

    TLMDGridHack(MyGrid).IncludeChange(cfData);

    Does it create a temporary TLMDGridHack object owned by MyGrid and call IncludeChange on it? If so, I don't know how to translate that... IncludeChange is protected in the C++ Builder TLMDGrid class so I can't call it in this way nor can I instantiate a TLMDGridHack object as it doesn't implement the required virtual functions...

    Anyhow,

    I'll try creating a Delphi unit with your code in a procedure and add it to my program and see if it helps...


    Andy
    (Using my home sign on as not in the office today)


  • edited August 2023 Posts: 0Vote Up0Vote Down
    Eugene 

    I've figured out what the Delphi code does (with the aid of AI lol) and have created my Delphi unit that ought to be able to access the protected functions to make the grid update. I'm away from the office today, but will test tomorrow...

    It is possible to pull off this hack in C++, but the syntax is awful... Again, I'm testing it now and will post results and the C++ once I'm sure it's working...

    Andy
  • edited August 2023 Posts: 0Vote Up0Vote Down
    Ok - both the Pascal and C++ versions work. In case anyone wants it, here's how to access the functions in C++:

    In a header file (so this can be shared around), put this code:

    //--------------------------------
    //Hack to access TLMDGrid's protected IncludeChange function
    template<typename Tag, typename Tag::type M>
    struct IncludeChange
    {
    friend typename Tag::type get(Tag) {
    return M;
    }
    };

    struct A_access_IncludeChange
    {
    typedef void __fastcall (TLMDCustomGrid::*type)(TLMDGridChangeFlag);
    friend type get(A_access_IncludeChange);
    };

    template struct IncludeChange<A_access_IncludeChange, &TLMDCustomGrid::IncludeChange>;

    //=======================================
    //Hack to access TLMDGrid's SyncGridStore protected function
    template<typename Tag, typename Tag::type M>
    struct SyncGridStore
    {
    friend typename Tag::type get(Tag) {
    return M;
    }
    };

    struct A_access_SyncGridStore
    {
    typedef void __fastcall (TLMDCustomGrid::*type)();
    friend type get(A_access_SyncGridStore);
    };

    template struct SyncGridStore<A_access_SyncGridStore,
    &TLMDCustomGrid::SyncGridStore>;
    //-----------------------------------------------------

    In the CPP file where data is added to the custom data, use this syntax to update the grid:

    //add data row(s) to the custom data
    LMDGrid1->BeginUpdate();
    (LMDGrid1->*get(A_access_IncludeChange()))(cfData);
    (LMDGrid1->*get(A_access_SyncGridStore()))();
    LMDGrid1->EndUpdate();

    And the grid updates!

    I'm guessing this code is as good an advert for staying with Delphi as you'll ever get!

    Will future releases of TLMDGrid fix this issue, so this horrible code can be removed after we update?

    Andy
  • Ok. I will think...
  • By the way, this can be done easier in C++:

    class A
    {
    protected:
    void P() { ShowMessage("Ok"); }
    };

    class B: A
    {
    public:
    void CallProtectedP() { P(); }
    };

    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      A *a = new A();
      ((B*)a)->CallProtectedP();
    }
Sign In or Register to comment.