delphilayouttgridpanel

Delphi TGridPanel - dynamically hide some rows


I have grid panel 16 x 4 like this one:

enter image description here

Sometimes i want to hide some rows and to move bottom rows up. When I set component visible property to false the layout is not updated:

enter image description here

Nevertheless the row size type is set to auto:

enter image description here

Why the component don't set row height to zero when there is nothing to display?


Solution

  • Why the component don't set row height to zero when there is nothing to display ?

    Because the row is considered as empty only if there are no components in all columns in that row, not if they're visible or not. So the same returns the IsRowEmpty method. To workaround this, you'd need to be notified by the cell component about its visibility change. When this notification is generated, you can check the row just like the IsRowEmpty method does, except you'll check if the controls are visible, not if they're assigned. Based on the result of such method, you can then set the size of the Value to 0 to hide the row.

    With a help of interposed class, the method for checking if all controls in a row or column are visible, you might write something like this. Those methods return True, when all existing controls in a certain row or column are visible, False otherwise:

    uses
      ExtCtrls, Consts;
    
    type
      TGridPanel = class(ExtCtrls.TGridPanel)
      public
        function IsColContentVisible(ACol: Integer): Boolean;
        function IsRowContentVisible(ARow: Integer): Boolean;
      end;
    
    implementation
    
    function TGridPanel.IsColContentVisible(ACol: Integer): Boolean;
    var
      I: Integer;
      Control: TControl;
    begin
      Result := False;
      if (ACol > -1) and (ACol < ColumnCollection.Count) then
      begin
        for I := 0 to ColumnCollection.Count -1 do
        begin
          Control := ControlCollection.Controls[I, ACol];
          if Assigned(Control) and not Control.Visible then
            Exit;
        end;
        Result := True;
      end
      else
        raise EGridPanelException.CreateFmt(sInvalidColumnIndex, [ACol]);
    end;
    
    function TGridPanel.IsRowContentVisible(ARow: Integer): Boolean;
    var
      I: Integer;
      Control: TControl;
    begin
      Result := False;
      if (ARow > -1) and (ARow < RowCollection.Count) then
      begin
        for I := 0 to ColumnCollection.Count -1 do
        begin
          Control := ControlCollection.Controls[I, ARow];
          if Assigned(Control) and not Control.Visible then
            Exit;
        end;
        Result := True;
      end
      else
        raise EGridPanelException.CreateFmt(sInvalidRowIndex, [ARow]);
    end;
    

    And the usage shown for the first row:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      // after you update visibility of controls in the first row...
      // if any of the controls in the first row is not visible, change the 
      // row's height to 0, what makes it hidden, otherwise set certain height
      if not GridPanel1.IsRowContentVisible(0) then
        GridPanel1.RowCollection[0].Value := 0
      else
        GridPanel1.RowCollection[0].Value := 50;
    end;