Question

Working on Delphi XE2, no 3rd party components/suites, nothing fancy.

Got a TCategoryPanelGroup (catPanGroup) on a form. I can easily add as many TCategoryPanel(s) as I need with:

procedure TSomeForm.PopulateGrp(Sender: TObject);
var catPanel: TCategoryPanel;
  x: word;
begin
  x := 0;
  while x < 9 do
  begin
    catPanel := catPanGroup.CreatePanel(Self) as TCategoryPanel;
    // Also tried the line below, using the panel group as the owner
    // catPanel := catPanGroup.CreatePanel(catPanGroup) as TCategoryPanel;
    //it also works without the following line
    catPanel.PanelGroup := catPanGroup;
    catPanel.Caption := 'and nothing else matters';
    Inc(x);
  end; //loop
end;

I don't care about the panel order, don't care (yet) how it looks, I can insert labels, textboxes and buttons inside these panels, they work as they should, no problems. I exit the application and no (apparent) leaks.

However, the application its a bit dynamic and need to remove a panel, lets say the last one. So, my immediate reaction is to:

var catPanel: TCategoryPanel;
begin
  catPanel := catPanGroup.Panels[catPanGroup.Panels.Count - 1];
  catPanGroup.Panels.Remove(catPanel);
end;

Or:

var catPanel: TCategoryPanel;
begin
  catPanGroup.Panels.Delete(catPanGroup.Panels.Count - 1);
end;

Even:

var catPanel: TCategoryPanel;
begin
  catPanel := catPanGroup.Panels[catPanGroup.Panels.Count - 1];
  catPanGroup.Panels.Remove(catPanel);
  catPanGroup.RemoveControl(catPanel);
  //catPanel.PanelGroup := nil; <- can't do, it raises an exception
end;

And when things were not working I:

  catPanGroup.Panels.Clear();
  //and rebuild every single panel

So ¿what's the error? On some cases there is no error but when I exit the application I always get an exception (access violation). ¿Maybe comes from the controls that I inserted inside the TCategoryPanel? Nope, I still get access violations without creating any controls on those panels. And the exception only pops when I delete (or try to delete) a panel. Will try at home on XE3 shortly.

¿Is anybody able to create and delete a TCategoryPanel on run-time?

Was it helpful?

Solution

The RemovePanel method is private, but you can use a class helper to gain access to such procedure.

Try this

Type
  TCategoryPanelGroupHelper = class helper for TCustomCategoryPanelGroup
  public
    procedure RemovePanel_(Panel: TCustomCategoryPanel);
  end;

{ TCategoryPanelGroupHelper }

procedure TCategoryPanelGroupHelper.RemovePanel_(Panel: TCustomCategoryPanel);
begin
  Self.RemovePanel(Panel);
end;

And use like so

  //This code will remove the first panel, be sure to check the bounds of the index passed.   
  catPanGroup.RemovePanel_(TCustomCategoryPanel(catPanGroup.Panels[0]));

OTHER TIPS

It looks as if though a panel is never meant to be removed. The panel removal code in VCL (TCustomCategoryPanelGroup.RemovePanel) is private, and only called from the category panel destructor and when setting a new parent panel group for a panel. In the latter case, VCL makes sure the new parent exists (not nil), and raises an exception otherwise.

Below is a not very nice workaround, it creates a temporary panel group to host the to be removed panel:

var
  catPanel: TCategoryPanel;
  dummy: TCategoryPanelGroup;
begin
  catPanel := catPanGroup.Panels[catPanGroup.Panels.Count - 1];

  dummy := TCategoryPanelGroup.Create(nil);
  try
    dummy.Visible := False;
    dummy.Parent := Self;
    catPanel.PanelGroup := dummy;
  finally
    dummy.Free;
  end;

This works for me :

procedure zapPanels(sender : tobject);
var
idx : integer;
x : tCategoryPanel;
begin
for idx := ((sender as tCategoryPanelGroup).Panels.Count)-1 downto 0 do
  begin
  x := (sender as tCategoryPanelGroup).Panels.Items[idx];
  x.Destroy;
  end;
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top