Automatyczne dopasowywanie panelu do zawartych w nim komponentów od lewej strony

0

Jak wiadomo, komponent Panel posiada właściwość AutoSize, która pozwala dopasowywać jego rozmiar do zawartych w nim komponentów. Problem polega na tym, że działa to tylko od prawej strony. Otóż po zastosowaniu właściwości AutoSize dla panelu o takim rozkładzie:
+----------+
| ____ |
||guzik| |
| |
+----------+
zostanie zamieniony na coś takiego:
+-------+
| ____ |
||guzik||
+-------+

Ja chciałbym uzyskać z pierwotnego panelu taką postać bez konieczności ręcznego przesuwania komponentów:
+-------+
||guzik||
+-------+
tzn. Panel ma się ze wszystkich stron (zależy mi głównie na lewej stronie) dopasował się do zawartych w nim komponentów. Proszę o pomoc.

1

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ę ;).

1 użytkowników online, w tym zalogowanych: 0, gości: 1