Reputation: 109
I'm using C# Winforms with the .NET Framework version 4.0
I have a panel which contains four labels all docked to the top of the panel. The middle two labels are hidden.
---Top---
Label One (Visible)
Label Two - (NOT Visible)
Label Three (NOT Visible)
Label Four - (Visible)
---Bottom---
When a button with the code below is clicked
private void btnShowLabels_Click(object sender, EventArgs e)
{
this.lblTwo.Visible = true;
this.lblThree.Visible = true;
}
labels two and three appear but their z-order gets mixed up as shown below.
---Top---
Label One (Visible)
Label Three (Visible)
Label Two - (Visible)
Label Four - (Visible)
---Bottom---
Why is the z-order getting changed and how can I stop this happening.
I realise I could re-order all the labels using BringToFront()
inside the click event but this feels like overkill especially for more complex docking arrangements.
Upvotes: 5
Views: 3277
Reputation: 11
For my application, the user would select the number of building panels (up to 5) they wanted in a combobox, and the program would then display a numbered panel for each where they could enter the dimensions (height, width, thickness) for each panel. There was a panel created with a header label with the panel number along with textboxes and labels for height, width, and thickness. The panels were all docked left in their containing panel to control layout. Unfortunately, hiding and showing the panels based upon the selected value in the combobox resulted in the panels being displayed in semi-random order.
private void cboNumberOfPanels_SelectedIndexChanged(object sender, EventArgs e)
{
int numberOfPanels;
int.TryParse(cboNumberOfPanels.SelectedItem.ToString(), out numberOfPanels);
pnlPanelDimensions1.Visible = numberOfPanels >= 1;
pnlPanelDimensions2.Visible = numberOfPanels >= 2;
pnlPanelDimensions3.Visible = numberOfPanels >= 3;
pnlPanelDimensions4.Visible = numberOfPanels >= 4;
pnlPanelDimensions5.Visible = numberOfPanels >= 5;
}
I tried using the .SetChildIndex() suggestion above, but still ran into issues on the second selection. For example, if I selected 1, pnlPanelDimensions1 would display in the correct position. If then chose 3, I would get pnlPanelDimensions2 displayed first, followed by pnlPanelDimensions3, and finally pnlPanelDimensions1. On all subsequent changes after the second, everything would display correctly.
I did finally find an option that worked correctly every time in my solution:
int numberOfPanels;
int.TryParse(cboNumberOfPanels.SelectedItem.ToString(), out numberOfPanels);
pnlPanelDimensions1.Visible = numberOfPanels >= 1;
pnlPanelDimensions1.BringToFront();
pnlPanelDimensions2.Visible = numberOfPanels >= 2;
pnlPanelDimensions2.BringToFront();
pnlPanelDimensions3.Visible = numberOfPanels >= 3;
pnlPanelDimensions3.BringToFront();
pnlPanelDimensions4.Visible = numberOfPanels >= 4;
pnlPanelDimensions4.BringToFront();
pnlPanelDimensions5.Visible = numberOfPanels >= 5;
pnlPanelDimensions5.BringToFront();
Upvotes: 0
Reputation: 81
Setting a Control.Visible = True
changes the Z-order sometimes. It seems to depend to the handle creation.
For me this (obviously meaningless) statement helped perfectly:
foreach (Control ctrl in FlpDetails.Controls)
{
IntPtr DummyHandle = ctrl.Handle;
}
It forces all controls to create the handles.
After that control.visible = true
doesn't change the Z-order anymore.
I got that solution from an external website, which now forwards to a fishing website.
Upvotes: 8
Reputation: 1431
Docking order seems to be a little different from z-order, and with SetChildIndex you'll still have to assign each label's .Visible
property in a certain order. I've played around with this trying to get lbl1 and lbl4 to appear in different order but they always stay in their position. I think your best bet is to just call the "middle" labels in "reverse" order of what you would normally think.
EDIT: Here's a way you can always keep the same dock order while not having to worry about setting each label's visible property in order all the time. Just create this event handler that you can attach to each docked label's VisibleChanged
event:
void GenericDockedLabel_VisibleChanged(object sender, EventArgs e)
{
this.Controls.SetChildIndex(lbl1, 3);
this.Controls.SetChildIndex(lbl2, 2);
this.Controls.SetChildIndex(lbl3, 1);
this.Controls.SetChildIndex(lbl4, 0);
}
Props to @Mark for the finding the SetChildIndex
Upvotes: 5