Handling a layout event
I was asked today the correct way to size a panel with a label in it. The panel is a header for a column of UI, which seems to be a common pattern in applications today. The question was: when I resize the panel, how can I make sure that the height of the panel accommodates all the text of the label?
Using Everett, we can easily whip together a sample that does this.
I’ve created new Windows Forms application (using Visual Studio 2003)
On the form, I have dropped two panels and a splitter in this order:
sidePanel – a panel Dock.Left to accommodate our header and a treeview
splitter1 – a splitter control Dock.Left to split between sidePanel and appPanel. The MinSize is set to 100 so that we dont get strange wrapping effects.
appPanel – a panel Dock.Fill to accommodate the main portion of the application.
Within the sidePanel I have dropped
headerPanel – a panel Dock.Top, to encapsulate the header text
treeView – a tree view Dock.Fill, since that seems to be popular
Within the headerPanel I have dropped
headerLabel – a label set to Dock.Fill
For extra fun I’ve sunk the headerPanel’s paint event and filled it with an “interesting” linear gradient brush fill.
Now for the part we’re interested in. When the splitter moves (and thus the size of the headerPanel changes) we want to change the height of the headerPanel so that it will accommodate all of the text on the label. We should provide enough room so that the label does not clip a portion of the text when the headerPanel is resized.
The magic to perform here is to handle the headerPanel’s layout event. When the size has changed for the headerPanel, its layout event will get called. We should measure the text of the label given the current width of the panel, and adjust the height of the panel to accomodate it.
private void headerPanel_Layout(object sender, LayoutEventArgs e) {
// measure the expected size of the label given the current width
// and set the height accordingly.
using (Graphics g = Graphics.FromHwnd(headerLabel.Handle)) {
headerLabel.Size = g.MeasureString(
headerLabel.Text,
headerLabel.Font,
headerPanel.Width).ToSize();
headerPanel.Height = headerLabel.Height;
}
}
In Whidbey, we have added several new controls to handle this feature more gracefully. Next time: how to achieve the same sample using the SplitContainer and TableLayoutPanel.