0

I need to add a simple at the bottom of an existing view. It is composed of nested panels in a code which I know is not proper. But what I want given my available time is (simple as it sounds) to add my link below what is existing.

In a few words, there is a ControlCollection object being displayed (this.Controls), and I can't locate an element (LinkLabel or TableLayoutPanel) below the other elements.

Here is the minimal existing code :

private void SetAppearance()
{
    pnlTitle = new Panel();
    pnlTitle.x = ...
    this.Controls.Add(pnlTitle);

    lblTitle = new Label();
    lblTitle.x = ...
    pnlTitle.Controls.Add(lblTitle);

    tlpnlCountryOfOrigin = new TableLayoutPanel();
    tlpnlCountryOfOrigin.x = ...
    pnlTitle.Controls.Add(tlpnlCountryOfOrigin);

    CountryOfOrigin = new Label();
    CountryOfOrigin.x = ...
    tlpnlCountryOfOrigin.Controls.Add(CountryOfOrigin, 0, 0);

    cbbCountryOrigin = new ComboBoxWithBorders();
    cbbCountryOrigin.x = ...
    tlpnlCountryOfOrigin.Controls.Add(cbbCountryOrigin, 1, 0);

    pnlSupportInfo = new TableLayoutPanel();
    pnlSupportInfo.x = ...
    this.Controls.Add(pnlSupportInfo);
}

And I am just basically wanting to add my LinkLabel at the bottom of that, with that :

lnkSendLogs = new LinkLabel
{
    Font = new Font(ArialBold12px, FontStyle.Regular | FontStyle.Underline),
    AutoSize = true,
    LinkColor = InfomaxConstants.Colors.Red,
    Margin = new Padding(0),
    Text = LabelManager.GetLabel("TEXTTOGETLABEL")
};
this.Controls.Add(lnkSendLogs);

Or even with a nested TableLayoutPanel (which I know is not a good practice) :

tlpnlSendLogs = new TableLayoutPanel();
tlpnlSendLogs.ColumnCount = 2;
tlpnlSendLogs.ColumnStyles.Clear();
tlpnlSendLogs.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100));
tlpnlSendLogs.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
lnkSendLogs = new LinkLabel
{
    Font = new Font(ArialBold12px, FontStyle.Regular | FontStyle.Underline),
    AutoSize = true,
    LinkColor = InfomaxConstants.Colors.Red,
    Margin = new Padding(0),
    Text = LabelManager.GetLabel("TEXTTOGETLABEL")
};      
lnkSendLogs.Dock = DockStyle.Fill;
tlpnlSendLogs.Controls.Add(lnkSendLogs, 0, 0);
this.Controls.Add(tlpnlSendLogs);

But the link is always appearing behind other elements, instead of below them.

The rendered

The question is thus the very basic : How to add a simple LinkLabel appearing at the bottom of a view containing a few elements like Panels and TableLayoutPanels ?

Gaël
  • 117
  • 1
  • 2
  • 17
  • The last two lines you show are contradictory. – TaW Apr 11 '18 at 08:21
  • Yes sorry this is not what I did in the code. Updating it – Gaël Apr 11 '18 at 08:26
  • Not sure what you are actually doing. If you add the new control to a TableLayoutPanel it will be added to the next free cell; if there is none a new row will be created. Any cell can only hold one control, although it may be too small to show it completely. But if you add to pretty much anyother type of control eg form or Panel it will sit at the relative location (0,0) until you move it to a suitaly spot.. For some layouts it may even be ok to simply do a BringToFront but usually you need to set the position with a little care, maybe newcontrol.Top=otherControl.Bottom etc.. – TaW Apr 11 '18 at 08:59
  • @TaW this.Controls is a ControlCollection and we can add an item through Add(element), but it seems we can't choose the location - not like with a TableLayoutPanel with which we can through TableLayoutPanel.Add(element, x, y). This ControlCollection contains the three Controls, but the third one (the one I added) is not displayed after the two firsts) – Gaël Apr 11 '18 at 09:04
  • But every Control has X/Left & Y/Top properties. – TaW Apr 11 '18 at 09:07
  • @TaW Both two first Controls are of Location {X=0 Y=0}, as the third one – Gaël Apr 11 '18 at 09:48
  • 1
    Well, that seems to be the mistake. They all sit at (0,0) so they overlap.. You need to set the locations! You can also set Dock=Bottom for the one you want at the bottom; but this may or may not look like you want it to.. – TaW Apr 11 '18 at 12:21
  • @TaW It actually changes the position of the LinkLabel, yes. Thing is that a DockStyle.Bottom put it at the bottom of the form, and not at the bottom of the previous second element. I must probably rearrange the position of the elements, but I still can't get why the two firsts are visually well located underneath one another – Gaël Apr 11 '18 at 12:36
  • 1
    Yes, that sounds funny. I usually add a borderstyle.single for testing to all controls so I can see their actual extent.. – TaW Apr 11 '18 at 13:07
  • 1
    To place a control `ctl` at the bottom of a Controls collection of a control `container` you can write: `ctl.Location = new Point(0, container.Height - ctl.Height);` You may also want to anchor it there: `ctl.Anchor |= AnchorStyles.Bottom;` You would still have to avoid overlapping other controls. For more fluent layout look into a FlowLayoutPanel. – TaW Apr 11 '18 at 13:31

1 Answers1

0

The first problem was that the controls had no location settings, which makes room for random and unwanted things.

Two things to have in mind for the ControlCollection elements:

  • Locate them
  • Order them

The thing to know is that the Controls of a ControlCollection are ordered based on their index, AND the one of bigger index will be the one the most at the border of the container (whatever the order in which the children elements anchor are being defined) (https://stackoverflow.com/a/7685041/6617804)

A solution is

1-To set the position of all the ControlCollection elements to the top of their container

pnlTitle.Dock = DockStyle.Top;
pnlSupportInfo.Dock = DockStyle.Top;
tlpnlSendLogs.Dock = DockStyle.Top;

Or the exact same :

pnlTitle.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
pnlSupportInfo.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
tlpnlSendLogs.Anchor = (AnchorStyles.Left | AnchorStyles.Top);

2.1-To arrange the child in the opposite order If we need to (in my case where we want to display them in the opposite order)

this.Controls.SetChildIndex(pnlTitle, 2);
this.Controls.SetChildIndex(pnlSupportInfo, 1);
this.Controls.SetChildIndex(tlpnlSendLogs, 0);

2.2-OR to add them directly in the order they need to be for the display :

this.Controls.Add(tlpnlSendLogs);
this.Controls.Add(pnlSupportInfo);
this.Controls.Add(pnlTitle);

Instead of :

this.Controls.Add(pnlTitle);
this.Controls.Add(pnlSupportInfo);
this.Controls.Add(tlpnlSendLogs);
Gaël
  • 117
  • 1
  • 2
  • 17