I'm having the STRANGEST thing ever. I'm currently working on my own control, and to make things easier, I decided to derive most things from a panel.
I'm building a small "toolbar" with buttons on it. If you select the top-button, the control collapses and shows it's child buttons.
So, I have a ButtonBar(Main control), a ButtonBand(Holds the top-level button and the a contentpane) and ContentPane(Holds all the other buttons).
Well, I create a new ButtonBar, call ButtonBar.AddBand(caption, contentPane) which looks like this:
public void AddBand(string caption, ContentPane pane)
{
if (pane == null) // Sanity check
throw new NullReferenceException("ContentPane is null");
int index = Controls.Count;
ButtonBand band = new ButtonBand(caption, pane, new BandInfo(this, index));
RecalcLayout(band, index);
this.Controls.Add(band);
}
Now, all the code works here. The RecalcLayout works fine(It adjusts the size of the controls). However, after calling Controls.Add(band), it goes nuts. I added a ComponentRemoved eventhandler to the class and it gets triggered. The strangest thing is, I never call Remove() or similar on the control. The framework does it by itself.
If you're interested in the complete source(It's not too big):
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Toolmaker
{
internal class BandInfo
{
public ButtonBar buttonBar;
public int index;
public BandInfo(ButtonBar parent, int ind)
{
buttonBar = parent;
index = ind;
}
}
/// <summary>
/// Summary description for ButtonBar.
/// </summary>
public class ButtonBar : System.Windows.Forms.Panel
{
private int buttonHeight;
private int selection = -1;
public ButtonBar()
{
buttonHeight = 25;
}
public void AddBand(string caption, ContentPane pane)
{
if (pane == null)
throw new NullReferenceException("ContentPane is null");
int index = Controls.Count;
ButtonBand band = new ButtonBand(caption, pane, new BandInfo(this, index));
RecalcLayout(band, index);
this.Controls.Add(band);
}
private void RecalcLayout(ButtonBand band, int index)
{
int posX = 0;
int height = buttonHeight;
if (index >= 1)
posX = Controls[index - 1].Location.Y + Controls[index - 1].ClientSize.Height;
// Set size/location of the band
band.Size = new Size(this.ClientSize.Width, band.CalcHeight());
band.Location = new Point(0, posX);
// Set the size/location of the top button
band.Controls[0].Size = new Size(band.ClientSize.Width, buttonHeight);
band.Controls[0].Location = new Point(0, 0);
if (index == selection)
height = band.Controls[1].Controls.Count * buttonHeight;
band.Controls[1].Size = new Size(band.ClientSize.Width - 10, height);
band.Controls[1].Location = new Point(ClientRectangle.Width, 0);
}
private void RedrawBands()
{
for (int index = 0; index < this.Controls.Count; ++index)
{
string st = Controls[index].Text;
ButtonBand band = this.Controls[index] as ButtonBand;
int y = band.Controls[0].Controls.Count;
int i = band.Controls.Count;
RecalcLayout(band, index);
}
}
public void SelectBand(int selection)
{
this.selection = selection;
RedrawBands();
}
}
internal class ButtonBand : System.Windows.Forms.Panel
{
BandInfo info = null;
ContentPane contentPane = null;
public ButtonBand(string caption, ContentPane pane, BandInfo info)
{
this.info = info;
this.contentPane = pane;
Button btn = new Button();
btn.Text = caption;
Controls.Add(btn);
Controls.Add(contentPane);
btn.Click += new EventHandler(OnClick);
this.ControlRemoved += new ControlEventHandler(OnControlRemoved);
}
public int CalcHeight()
{
return (25 + contentPane.Controls.Count * 25);
}
private void OnControlRemoved(object sender, ControlEventArgs e)
{
//MessageBox.Show(this, "Control removed from band");
}
private void OnClick(object sender, EventArgs e)
{
info.buttonBar.SelectBand(info.index);
}
}
public class ContentPane : System.Windows.Forms.Panel
{
public ContentPane()
{
}
public void AddButton(string caption, EventHandler eventHandler)
{
Button btn = new Button();
btn.Text = caption;
btn.Size = new Size(this.ClientSize.Width, 25);
btn.Location = new Point(10, Controls.Count * 25);
Controls.Add(btn);
}
public int CalculateSize()
{
return (Controls.Count * 25);
}
}
}
Ideas on this?
Toolmaker