AlignContainer

Ein ContainerControl zur optimalen Ausrichtung beliebiger Inhalte

Was kann dieses Control?

  • Es funktioniert wie ein Panel.
  • Es richtet Inhalt nach Bedarf horizontal (rechts / links / zentriert) und vertikal (oben / unten / zentriert) aus.
  • Es sorgt für automatische Anzeige von ScrollBars.
  • Bei Größenänderung des AlignContainers wird eine gerade mit Scrollen erreichte Position beibehalten.
  • Nach Bedarf kann festgelegt werden, wie sich das Control verhält, wenn der Inhalt kleiner als der Container wird. Entweder behält der Inhalt dabei seine ursprüngliche Ausrichtung bei, er kann auch zentriert werden.
  • Für erbende Klassen stellt es ein paar nützliche Eigenschaften zur Verfügung. Dies wären:
    • ContentBackRectangle - Gibt ein Rechteck zurück, das Position und Größe des aktuell im Control sichtbaren Inhalts-Ausschnittes beschreibt.
    • ContentRectangle - Gibt ein Rechteck zurück, das Position und Größe des gesamten im Control enthaltenen Inhalts beschreibt .
    • ValuesRectangle - Gibt ein Rechteck zurück, das den Wertbereich (Start-Pixel und Länge in Pixeln) des aktuell im Control sichtbaren Inhalts-Ausschnittes beschreibt.
  • Das Control besitzt einen ParentControlDesigner, der erlaubt, Controls auch zur Entwurfszeit im Windows Forms Designer hinzuzufügen oder zu entfernen. Ein Smart-Tag ermöglicht schnellen Zugriff auf die wichtigsten Properties.

AlignContainer in Aktion

Eigentlich wollte ich nur mal wieder ein anderes Control in einem Panel zentrieren. Dabei fiel mir auf, dass ich schon öfters Code für sowas geschrieben habe und es jedes Mal dasselbe ist. Auch fällt es mir dabei immer wieder relativ schwer, mich im System mit AutoScrollMinSize, AutoScrollPosition zurechtzufinden und eine Mausposition in die reale Position im gescrollten Container umzurechnen. So habe ich verschiedene Varianten versucht. Wahrscheinlich wäre es am einfachsten gewesen, ein ScrollableControl als Basis zu verwenden. Aber ich wollte einen sichtbaren Rahmen im selben Control haben und vielleicht auch meine eigenen GlassScrollBars verwenden. Um Unterstützung zur Entwurfszeit zu erhalten, habe ich mich dann für das ContainerControl entschieden.

Wie funktioniert das Ganze?

Über die Property ContentAlignment wird festgelegt, wie der Container enthaltene Child-Controls ausrichten soll. Fügt man nun ein Child-Control hinzu, wird berechnet, welchen Platz die Children beanspruchen, danach werden wenn notwendig ScrollBars mit passenden Werten angezeigt. Dann wird festgelegt, welche neue Position die Children innerhalb des Container-Controls erhalten sollen. Im Windows Forms Designer sieht das so aus, als hätte man einen Magneten im Control. Natürlich gibt's auch einen Handler für Größenänderung der Children.

Die Lösung für den Rahmen ist ein Kompromiss. Zunächst hatte ich beim Hinzufügen von Children einen Handler für das Paint-Ereignis der Children "vergeben", und dann den Rahmen über die Children "darüber gezeichnet". Das führte trotzdem zu Schlieren auf den Child-Controls beim Resize. So blieb mir nur der Umweg über im Vordergrund befindliche 1 Pixel breite Dummy-Controls. Schließlich funktionierte alles ohne Flackern.

Um die Positionierung der Inhalte und Anzeige der ScrollBars zu vereinfachen, habe ich eine Klasse namens ScrollRangeCalculator entworfen. Es gibt einen für die vertikale und einen für die horizontale ScrollBar. Er wird regelmäßig über die aktuelle Größe des ContainerControls und Größe des aktuellen Inhalts informiert, merkt sich den aktuellen Wert der ScrollBar und zeigt die ihm zugeordnete ScrollBar automatisch an.

Der Designer? Wollte mal experimentieren. So ein Control kann doch durchaus auch einen schönen Designer vertragen.

Als kleinen Zusatz habe ich mal einen ColorLabelContainer beigefügt, ein ContainerControl, das in seinem Kopfbereich ein farbiges Label zeichnet. Das besondere ist: Es lässt keine anderen Controls im Kopfbereich (dort wo das farbige Label erscheint) zu.

Kleiner Zusatz. Ein Container mit farbigem Label.