Mógłbyś spróbować czegoś takiego:
public partial class ShrinkingPanel : Panel {
public ShrinkingPanel() {
this.InitializeComponent();
}
// zmiana rozmiaru może zajść przy dodaniu nowej kontrolki
protected override void OnControlAdded(ControlEventArgs e) {
base.OnControlAdded(e);
this.RecalculateSize();
}
// albo przy usunięciu starej
protected override void OnControlRemoved(ControlEventArgs e) {
base.OnControlRemoved(e);
this.RecalculateSize();
}
// tak czy inaczej szukamy najmniejszego prostokąta pokrywającego wszystkie `dzieci` kontrolki
public void RecalculateSize() {
if (Controls.Count > 0) { // jeśli nie ma kontrolek to nie ma do czego się kurczyć
Rectangle bounds = this.Controls[0].Bounds;
foreach (Control control in this.Controls) {
bounds = Rectangle.Union(bounds, control.Bounds);
}
// Alternatywnie, używając LINQ
// Rectangle bounds = Controls.Cast<Control>().Select(x => x.Bounds)
// .Aggregate(Rectangle.Union);
this.Size = bounds.Size;
this.ChangePosition(bounds.X, bounds.Y);
}
}
// wspomniane przesuwanie wszystkich `dzieci` na nową pozycje
void ChangePosition(int x, int y) {
foreach (Control control in Controls) {
control.Location = new Point(control.Location.X - x, control.Location.Y - y);
}
this.Location = new Point(this.Location.X + x, this.Location.Y + y);
}
}
Ale na 90% nie będzie to działało tak jak chcesz (tzn. zadziała dobrze dla usuwania kontrolek, ale poza tym może być nieintuicyjne).
Dlaczego: pozycja kontrolek w panelu jest przechowywane relatywnie do panelu (i ogólnie, bazowej kontrolki, co ułatwia np. przesuwanie). Oznacza to że jeśli chcesz skurczyć
panel od lewej strony, musisz przesunąć wszystkie kontrolki w panelu w lewo
poza tym że sam panel w prawo
.
Oczywiście może się okazać że istnieje do tego gotowe rozwiązanie a ja próbuje wymyślić koło od nowa, ale niczego takiego nie kojarzę ;).