Paul Endersby
Paul Endersby

Reputation: 83

Set DevExpress Grid Tableview Editable property and determine its parent via RTTI

I have a project with multiple TcxGrids on. The class hierarchy structure of the grids in my project are as follows:

TForm->TPanel->TcxPageControl->TcxTabSheet(subclassed)->TcxGrid->TcxGridLevel->TcxGridDBBandedTableView

In my subclassed TcxTabSheet I have added a new property "ReadOnly" that when set loops over the tabsheets controls and sets them to enabled/disabled respectively.

When a TcxGrid controls enabled property is set to true, the user can no longer interact with the grid at all (including navigating).

It seems I need to set the OptionsData.Editing property on the TcxGridDBBandedTableView to achieve a readonly but still navigable grid control.

Simple enough until you factor in that I want to do this in a loose coupled manner which I think leaves me the option of RTTI.

I have written the following code that loops over the forms controls (looping over the tabs controls or components doesn't give me access to the TcxGridDBBandedTableView). Once the control is found I can set its editing property via RTTI. I just don't seem to able to determine if that TcxGridDBBandedTableView belongs to the TabSheet it sits on.

var
  compIdx: Integer;
begin
  for compIdx := 0 to Pred(ComponentCount) do
    if (Components[compIdx].ClassNameIs('TcxGridDBBandedTableView')) then
      SetOrdProp(GetObjectProp(Components[compIdx], 'OptionsData'), 'Editing', Ord(not FReadOnly));
end;

TL;DR How can I determine what pagectrl tab a cxgrid is on and set its TableView.OptionsData.Editable property without adding any devexpress units to the uses clause of the unit.

Upvotes: 0

Views: 2087

Answers (1)

David Heffernan
David Heffernan

Reputation: 612954

You are iterating over the components owned by the form. I think that's the wrong approach. You should be looking at the parent/child relationship rather than ownership. Not least because it's perfectly possible for a form to contain controls that it does not own. So, your approach can fail to find controls, particularly dynamically created controls.

So, if you have a tabsheet (or indeed any windowed control), you can iterate over its children like this:

for i := 0 to TabSheet.ControlCount-1 do
  DoSomething(TabSheet.Controls[i]);

If your target grid control is a direct descendent of the tabsheet then this will be enough. If it is more than one level deep in the hierarchy then you will need a recursive solution. I will leave that recursive solution as an exercise for you.

Suppose that you have a control and want to find the tabsheet that it sits inside, then you need to walk up the parent chain. Like this:

function GetParentOfClass(Control: TControl; AClass: TWinControlClass): TWinControl;
var
  Control: TWinControl;
begin
  while Assigned(Control) and not (Control is AClass) do
    Control := Control.Parent;
  Result := TWinControl(Control);
end;

Upvotes: 0

Related Questions