# Controls

Bei `<span>System.Windows.Forms</span>` sind mit Controls grundsätzlich die Klassen gemeint, die von `<span>System.Windows.Forms.Control</span>` erben. Also die visuellen bzw. interaktiven Elemente, die du auf einer Form platzieren kannst.

# Button

Ein `Button` ist ein Steuerelement, mit dem der Benutzer **Aktionen auslösen** kann.

Im Gegensatz zu Controls wie `TextBox`, `ListBox` oder `CheckedListBox` speichert ein `Button` keine Daten. Er dient ausschließlich dazu, eine Aktion auszuführen, beispielsweise das Speichern einer Datei, das Öffnen eines Dialogs oder das Starten einer Berechnung.

---

## **Grundlagen**

Ein `Button` löst **eine Aktion** aus.

- `Button` → führt eine Aktion aus
- `<a href="https://doku.borinas.com/books/klassenwindowsforms/page/label" title="Label">Label</a>` → zeigt Informationen an
- `TextBox` → ermöglicht Texteingaben

#### Button erstellen

```powershell
# Klassisch
$button = New-Object System.Windows.Forms.Button

# .NET-Style
$button = [System.Windows.Forms.Button]::new()
```

#### Button hinzufügen

Ein `Button` wird wie jedes andere Control der `Controls`-Collection seines Parent-Containers hinzugefügt.

```powershell
$form.Controls.Add($button)

# oder

$tabPage.Controls.Add($button)
```

#### Click-Event hinzufügen

Die häufigste Aufgabe eines Buttons besteht darin, auf einen Mausklick zu reagieren.

```powershell
$button.Add_Click({
    param($sender, $e)

    Write-Host "Button wurde geklickt."
})
```

---

# **Eigenschaften**

<table id="bkmrk-eigenschaft-beschrei"><thead><tr><th>Eigenschaft</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`AutoSize`</td><td>Passt die Größe des Buttons automatisch an dessen Inhalt an.</td></tr><tr><td>`AutoEllipsis`</td><td>Kürzt zu langen Text automatisch mit `...`.</td></tr><tr><td>`BackColor`</td><td>Legt die Hintergrundfarbe des Buttons fest.</td></tr><tr><td>`DialogResult`</td><td>Gibt den Rückgabewert eines Dialogfensters beim Klick auf den Button an.</td></tr><tr><td>`Dock`</td><td>Dockt den Button an einer Seite seines Parent-Containers an.</td></tr><tr><td>`Enabled`</td><td>Legt fest, ob der Button verwendet werden kann.</td></tr><tr><td>`FlatAppearance`</td><td>Enthält Darstellungseigenschaften für flache Buttons.</td></tr><tr><td>`FlatStyle`</td><td>Bestimmt das Erscheinungsbild des Buttons.</td></tr><tr><td>`Font`</td><td>Legt Schriftart, -größe und -stil fest.</td></tr><tr><td>`ForeColor`</td><td>Legt die Textfarbe fest.</td></tr><tr><td>`Image`</td><td>Zeigt ein Bild auf dem Button an.</td></tr><tr><td>`ImageAlign`</td><td>Bestimmt die Position des Bildes innerhalb des Buttons.</td></tr><tr><td>`ImageIndex`</td><td>Wählt ein Bild anhand seines Indexes aus der `ImageList` aus.</td></tr><tr><td>`ImageKey`</td><td>Wählt ein Bild anhand seines Namens aus der `ImageList` aus.</td></tr><tr><td>`ImageList`</td><td>Legt die Bildersammlung für den Button fest.</td></tr><tr><td>`Location`</td><td>Bestimmt die Position des Buttons im Parent-Container.</td></tr><tr><td>`Margin`</td><td>Legt den äußeren Abstand zu benachbarten Controls fest.</td></tr><tr><td>`MaximumSize`</td><td>Definiert die maximal zulässige Größe.</td></tr><tr><td>`MinimumSize`</td><td>Definiert die minimal zulässige Größe.</td></tr><tr><td>`Name`</td><td>Legt den internen Namen des Buttons fest.</td></tr><tr><td>`Padding`</td><td>Legt den Innenabstand zwischen Rand und Inhalt fest.</td></tr><tr><td>`Size`</td><td>Bestimmt Breite und Höhe des Buttons.</td></tr><tr><td>`TabIndex`</td><td>Legt die Reihenfolge der Tabulator-Navigation fest.</td></tr><tr><td>`TabStop`</td><td>Legt fest, ob der Button per Tabulator fokussiert werden kann.</td></tr><tr><td>`Text`</td><td>Bestimmt die sichtbare Beschriftung des Buttons.</td></tr><tr><td>`TextAlign`</td><td>Legt die Position des Textes fest.</td></tr><tr><td>`TextImageRelation`</td><td>Bestimmt die Anordnung von Bild und Text.</td></tr><tr><td>`UseMnemonic`</td><td>Aktiviert Tastenkombinationen über `&` im Text.</td></tr><tr><td>`UseVisualStyleBackColor`</td><td>Verwendet das Windows-Design für den Hintergrund.</td></tr><tr><td>`Visible`</td><td>Legt fest, ob der Button sichtbar ist.</td></tr></tbody></table>

<details id="bkmrk-autosize-autosize-ty"><summary>AutoSize</summary>

#### **AutoSize**

**Typ** = `[System.Boolean]`

Der Wert von `AutoSize` legt fest, ob sich die Größe des Buttons automatisch an dessen Inhalt anpasst. Standardmäßig besitzt diese Eigenschaft den Wert `False`, wodurch ausschließlich die Eigenschaft `Size` die Größe bestimmt.

Ist `AutoSize` auf `True` gesetzt, wird die Breite und Höhe des Buttons automatisch an den enthaltenen Text beziehungsweise das Bild angepasst.

```powershell
$button.AutoSize = $true
```

</details><details id="bkmrk-autoellipsis-autoell"><summary>AutoEllipsis</summary>

#### **AutoEllipsis**

**Typ** = `[System.Boolean]`

Der Wert von `AutoEllipsis` legt fest, ob zu langer Text automatisch mit `...` gekürzt werden soll, wenn dieser nicht vollständig dargestellt werden kann.

Standardmäßig ist diese Eigenschaft auf `False` gesetzt.

```powershell
$button.AutoEllipsis = $true
```

</details><details id="bkmrk-backcolor-backcolor-"><summary>BackColor</summary>

#### **BackColor**

**Typ** = `[System.Drawing.Color]`

Der Wert von `BackColor` legt die Hintergrundfarbe des Buttons fest.

Standardmäßig wird die Hintergrundfarbe durch das aktuelle Windows-Design bestimmt. Soll eine eigene Hintergrundfarbe verwendet werden, muss zusätzlich `UseVisualStyleBackColor` auf `$false` gesetzt werden.

```powershell
$button.UseVisualStyleBackColor = $false
$button.BackColor = "RoyalBlue"
```

> 💡 **Hinweis**  
> Solange `UseVisualStyleBackColor` aktiviert ist, wird `BackColor` häufig ignoriert.

</details><details id="bkmrk-dialogresult-dialogr"><summary>DialogResult</summary>

#### **DialogResult**

**Typ** = `[System.Windows.Forms.DialogResult]`

Der Wert von `DialogResult` legt fest, welcher Rückgabewert beim Anklicken des Buttons an ein modales Dialogfenster (`ShowDialog()`) zurückgegeben wird.

Standardmäßig besitzt diese Eigenschaft den Wert `None`. Wird beispielsweise `OK`, `Cancel` oder `Yes` festgelegt, schließt sich das Dialogfenster automatisch und `ShowDialog()` liefert den entsprechenden Wert zurück.

Diese Eigenschaft wird hauptsächlich in Dialogfenstern verwendet.

```powershell
$button.DialogResult = "OK"
```

</details><details id="bkmrk-dock-dock-typ-%3D-%5Bsys"><summary>Dock</summary>

#### **Dock**

**Typ** = `[System.Windows.Forms.DockStyle]`

Der Wert von `Dock` legt fest, an welcher Seite seines Parent-Containers der Button angedockt wird. Standardmäßig besitzt diese Eigenschaft den Wert `None`, wodurch Position und Größe ausschließlich über `Location` und `Size` bestimmt werden.

Alternativ kann der Button am oberen (`Top`), unteren (`Bottom`), linken (`Left`) oder rechten (`Right`) Rand angedockt oder mit `Fill` über den gesamten verfügbaren Bereich ausgedehnt werden.

Im Gegensatz zu `Anchor` übernimmt `Dock` sowohl die Positionierung als auch die Größenanpassung des Controls.

```powershell
$button.Dock = "Fill"
```

</details><details id="bkmrk-enabled-enabled-typ-"><summary>Enabled</summary>

#### **Enabled**

**Typ** = `[System.Boolean]`

Der Wert von `Enabled` legt fest, ob der Button vom Benutzer verwendet werden kann.

Standardmäßig besitzt diese Eigenschaft den Wert `True`. Ist sie auf `False` gesetzt, wird der Button ausgegraut dargestellt und reagiert weder auf Maus- noch auf Tastatureingaben.

```powershell
$button.Enabled = $false
```

</details><details id="bkmrk-flatappearance-flata"><summary>FlatAppearance</summary>

#### **FlatAppearance**

**Typ** = `[System.Windows.Forms.FlatButtonAppearance]`

Der Wert von `FlatAppearance` enthält verschiedene Eigenschaften zur Darstellung eines Buttons mit dem `FlatStyle` `Flat` oder `Popup`.

Hierüber können unter anderem die Rahmenfarbe (`BorderColor`), Rahmenstärke (`BorderSize`) sowie die Hintergrundfarben beim Überfahren oder Anklicken angepasst werden.

```powershell
$button.FlatStyle = "Flat"

$button.FlatAppearance.BorderSize = 1
$button.FlatAppearance.BorderColor = "DodgerBlue"
```

> 💡 **Hinweis**  
> Die Eigenschaften von `FlatAppearance` wirken nur bei den Darstellungsarten `Flat` und teilweise `Popup`.

</details><details id="bkmrk-flatstyle-flatstyle-"><summary>FlatStyle</summary>

#### **FlatStyle**

**Typ** = `[System.Windows.Forms.FlatStyle]`

Der Wert von `FlatStyle` bestimmt das Erscheinungsbild des Buttons.

Standardmäßig besitzt diese Eigenschaft den Wert `Standard`. Alternativ stehen `Flat`, `Popup` und `System` zur Verfügung.

- **Standard** → Standarddarstellung
- **Flat** → flacher Button
- **Popup** → flach, hebt sich beim Überfahren hervor
- **System** → Darstellung vollständig durch Windows

```powershell
$button.FlatStyle = "Flat"
```

</details><details id="bkmrk-font-font-typ-%3D-%5Bsys"><summary>Font</summary>

#### **Font**

**Typ** = `[System.Drawing.Font]`

Der Wert von `Font` legt die Schriftart fest, mit der der Text des Buttons dargestellt wird.

Änderungen an dieser Eigenschaft beeinflussen sowohl Schriftart als auch Schriftgröße und Schriftstil.

```powershell
$button.Font = [System.Drawing.Font]::new( "Segoe UI", 10, "Bold" )
```

</details><details id="bkmrk-forecolor-forecolor-"><summary>ForeColor</summary>

#### **ForeColor**

**Typ** = `[System.Drawing.Color]`

Der Wert von `ForeColor` legt die Farbe fest, mit der der Text des Buttons dargestellt wird.

```powershell
$button.ForeColor = "White"
```

</details><details id="bkmrk-image-image-typ-%3D-%5Bs"><summary>Image</summary>

#### **Image**

**Typ** = `[System.Drawing.Image]`

Der Wert von `Image` legt das Bild fest, das auf dem Button angezeigt werden soll.

Standardmäßig besitzt diese Eigenschaft den Wert `$null`, wodurch kein Bild dargestellt wird. Ist sowohl ein Bild als auch ein Text vorhanden, bestimmt `TextImageRelation`, wie beide Elemente zueinander angeordnet werden.

```powershell
$button.Image = [System.Drawing.Image]::FromFile( "C:\Icons\Save.png" )
```

> 💡 **Hinweis**  
> Soll das Bild aus einer `ImageList` stammen, werden stattdessen die Eigenschaften `ImageList` sowie `ImageIndex` oder `ImageKey` verwendet.

</details><details id="bkmrk-imagealign-imagealig"><summary>ImageAlign</summary>

#### **ImageAlign**

**Typ** = `[System.Drawing.ContentAlignment]`

Der Wert von `ImageAlign` legt fest, an welcher Position das Bild innerhalb des Buttons dargestellt wird.

Standardmäßig befindet sich das Bild mittig (`MiddleCenter`). Zusammen mit `TextAlign` und `TextImageRelation` lässt sich die Anordnung von Bild und Text individuell festlegen.

```powershell
$button.ImageAlign = "MiddleLeft"
```

</details><details id="bkmrk-imageindex-imageinde"><summary>ImageIndex</summary>

#### **ImageIndex**

**Typ** = `[System.Int32]`

Der Wert von `ImageIndex` bestimmt den Index des Bildes innerhalb der zugewiesenen `ImageList`.

Standardmäßig besitzt diese Eigenschaft den Wert `-1`, wodurch kein Bild ausgewählt ist.

```powershell
$button.ImageList = $imageList
$button.ImageIndex = 0

```

> 💡 **Hinweis**  
> `ImageIndex` und `ImageKey` dienen demselben Zweck. Es sollte immer nur eine der beiden Eigenschaften verwendet werden.

</details><details id="bkmrk-imagekey-imagekey-ty"><summary>ImageKey</summary>

#### **ImageKey**

**Typ** = `[System.String]`

Der Wert von `ImageKey` legt den Namen eines Bildes innerhalb der zugewiesenen `ImageList` fest.

Im Gegensatz zu `ImageIndex` erfolgt die Auswahl hierbei über den Namen des Bildes.

```powershell
$button.ImageList = $imageList
$button.ImageKey = "Save"
```

</details><details id="bkmrk-imagelist-imagelist-"><summary>ImageList</summary>

#### **ImageList**

**Typ** = `[System.Windows.Forms.ImageList]`

Der Wert von `ImageList` legt die Bildersammlung fest, aus der der Button seine Bilder beziehen kann.

Die Eigenschaft selbst bestimmt noch kein Bild. Welches Bild angezeigt wird, wird anschließend über `ImageIndex` oder `ImageKey` ausgewählt.

```powershell
$button.ImageList = $imageList
$button.ImageIndex = 2
```

</details><details id="bkmrk-location-location-ty"><summary>Location</summary>

#### **Location**

**Typ** = `[System.Drawing.Point]`

Der Wert von `Location` legt die Position des Buttons innerhalb seines Parent-Containers fest.

Die Position wird über die X- und Y-Koordinate relativ zum Parent-Control angegeben.

```powershell
$button.Location = "20, 40"

```

> 💡 **Hinweis**  
> Ist zusätzlich `Dock` aktiviert, wird `Location` vom Layoutsystem automatisch verwaltet.

</details><details id="bkmrk-margin-margin-typ-%3D-"><summary>Margin</summary>

#### **Margin**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Margin` legt den äußeren Abstand des Buttons zu benachbarten Controls fest.

Die Eigenschaft wird hauptsächlich von Layout-Containern wie `FlowLayoutPanel` oder `TableLayoutPanel` berücksichtigt.

```powershell
$button.Margin = [System.Windows.Forms.Padding]::new(10)

```


</details><details id="bkmrk-maximumsize-maximums"><summary>MaximumSize</summary>

#### **MaximumSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `MaximumSize` legt die maximal zulässige Größe des Buttons fest.

Standardmäßig besitzt diese Eigenschaft den Wert `(0,0)`. Dadurch existiert keine Größenbegrenzung.

```powershell
$button.MaximumSize = "250, 50"
```

</details><details id="bkmrk-minimumsize-minimums"><summary>MinimumSize</summary>

#### **MinimumSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `MinimumSize` legt die minimal zulässige Größe des Buttons fest.

Unterschreitet eine Größenänderung diesen Wert, bleibt die festgelegte Mindestgröße erhalten.

```powershell
$button.MinimumSize = "120, 35"
```

</details><details id="bkmrk-name-name-typ-%3D-%5Bsys"><summary>Name</summary>

#### **Name**

**Typ** = `[System.String]`

Der Wert von `Name` legt den internen Namen des Buttons fest.

Der Name dient ausschließlich der Identifikation innerhalb des Programms und wird dem Benutzer nicht angezeigt. Besonders bei größeren Formularen erleichtert ein eindeutiger Name die spätere Verwaltung und den Zugriff auf Controls.

```powershell
$button.Name = "btnSave"
```

</details><details id="bkmrk-padding-padding-typ-"><summary>Padding</summary>

#### **Padding**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Padding` legt den Innenabstand zwischen dem Rand des Buttons und dessen Inhalt fest.

Dadurch kann zusätzlicher Abstand zwischen Rahmen, Text und Bild geschaffen werden.

```powershell
$button.Padding = [System.Windows.Forms.Padding]::new(8)
```

</details><details id="bkmrk-size-size-typ-%3D-%5Bsys"><summary>Size</summary>

#### **Size**

**Typ** = `[System.Drawing.Size]`

Der Wert von `Size` legt die Breite und Höhe des Buttons fest.

Standardmäßig wird die Größe ausschließlich durch diese Eigenschaft bestimmt. Ist `AutoSize` aktiviert, kann die Größe automatisch anhand des Inhalts berechnet werden.

```powershell
$button.Size = "120, 35"
```

</details><details id="bkmrk-tabindex-tabindex-ty"><summary>TabIndex</summary>

#### **TabIndex**

**Typ** = `[System.Int32]`

Der Wert von `TabIndex` legt die Reihenfolge fest, in der das Control den Fokus erhält, wenn der Benutzer die **Tabulator-Taste** betätigt.

Standardmäßig vergibt der Designer beziehungsweise die Reihenfolge der hinzugefügten Controls fortlaufende Werte. Das Control mit dem kleinsten `TabIndex` erhält den Fokus zuerst.

```powershell
$button.TabIndex = 2
```

> 💡 **Hinweis**  
> Die tatsächliche Tabulator-Reihenfolge ergibt sich aus dem Zusammenspiel von `TabIndex` und `TabStop`.

</details><details id="bkmrk-tabstop-tabstop-typ-"><summary>TabStop</summary>

#### **TabStop**

**Typ** = `[System.Boolean]`

Der Wert von `TabStop` legt fest, ob der Button über die **Tabulator-Taste** den Fokus erhalten kann.

Standardmäßig besitzt diese Eigenschaft den Wert `True`. Wird sie auf `False` gesetzt, überspringt die Tabulator-Navigation den Button, obwohl dieser weiterhin per Mausklick verwendet werden kann.

```powershell
$button.TabStop = $false
```

</details><details id="bkmrk-text-text-typ-%3D-%5Bsys"><summary>Text</summary>

#### **Text**

**Typ** = `[System.String]`

Der Wert von `Text` legt die sichtbare Beschriftung des Buttons fest.

Standardmäßig besitzt diese Eigenschaft den Wert `""` (leerer String). Der Text wird innerhalb des Buttons entsprechend der Eigenschaft `TextAlign` dargestellt.

```powershell
$button.Text = "Speichern"
```

Soll der Button ausschließlich ein Symbol enthalten, kann der Text leer bleiben.

```powershell
$button.Text = ""
```

</details><details id="bkmrk-textalign-textalign-"><summary>TextAlign</summary>

#### **TextAlign**

**Typ** = `[System.Drawing.ContentAlignment]`

Der Wert von `TextAlign` legt fest, an welcher Position der Text innerhalb des Buttons dargestellt wird.

Standardmäßig besitzt diese Eigenschaft den Wert `MiddleCenter`, wodurch der Text zentriert angezeigt wird.

In Kombination mit `ImageAlign` und `TextImageRelation` kann die Position von Text und Bild unabhängig voneinander festgelegt werden.

```powershell
$button.TextAlign = "MiddleRight"
```

</details><details id="bkmrk-textimagerelation-te"><summary>TextImageRelation</summary>

#### **TextImageRelation**

**Typ** = `[System.Windows.Forms.TextImageRelation]`

Der Wert von `TextImageRelation` legt fest, wie Text und Bild innerhalb des Buttons zueinander angeordnet werden.

Diese Eigenschaft besitzt nur dann eine sichtbare Auswirkung, wenn sowohl `Text` als auch `Image` beziehungsweise `ImageList` verwendet werden.

Folgende Werte stehen zur Verfügung:

- **Overlay** → Text und Bild liegen übereinander
- **ImageBeforeText** → Bild links vom Text
- **TextBeforeImage** → Text links vom Bild
- **ImageAboveText** → Bild oberhalb des Textes
- **TextAboveImage** → Text oberhalb des Bildes

```powershell
$button.Image = $image
$button.Text = "Speichern"

$button.TextImageRelation = "ImageBeforeText"
```

> 💡 **Hinweis**  
> Die genaue Position wird zusätzlich durch `ImageAlign` und `TextAlign` beeinflusst.

</details><details id="bkmrk-usemnemonic-usemnemo"><summary>UseMnemonic</summary>

#### **UseMnemonic**

**Typ** = `[System.Boolean]`

Der Wert von `UseMnemonic` legt fest, ob im Text enthaltene Mnemonics ausgewertet werden.

Standardmäßig besitzt diese Eigenschaft den Wert `True`.

Ein kaufmännisches Und (`&`) kennzeichnet den folgenden Buchstaben als Tastenkombination. Dieser Buchstabe wird unterstrichen und kann zusammen mit der **Alt-Taste** verwendet werden.

```powershell
$button.Text = "&Speichern"
```

Im Beispiel kann der Button mit **Alt + S** aktiviert werden.

Soll das Zeichen `&` hingegen als normales Zeichen dargestellt werden, muss es doppelt angegeben werden.

```powershell
$button.Text = "Speichern && Schließen"
```

</details><details id="bkmrk-usevisualstylebackco"><summary>UseVisualStyleBackColor</summary>

#### **UseVisualStyleBackColor**

**Typ** = `[System.Boolean]`

Der Wert von `UseVisualStyleBackColor` legt fest, ob der Button seine Hintergrundfarbe vom aktuellen Windows-Design übernimmt.

Standardmäßig besitzt diese Eigenschaft den Wert `True`. Dadurch bestimmt Windows die Darstellung des Buttons, wodurch eine einheitliche Optik mit dem Betriebssystem erreicht wird.

Soll eine eigene Hintergrundfarbe über `BackColor` verwendet werden, muss `UseVisualStyleBackColor` auf `$false` gesetzt werden.

```powershell
$button.UseVisualStyleBackColor = $false
$button.BackColor = "RoyalBlue"
```

> 💡 **Hinweis**  
> Solange `UseVisualStyleBackColor` aktiviert ist, wird `BackColor` häufig vollständig ignoriert.

</details><details id="bkmrk-visible-visible-typ-"><summary>Visible</summary>

#### **Visible**

**Typ** = `[System.Boolean]`

Der Wert von `Visible` legt fest, ob der Button sichtbar dargestellt wird.

Standardmäßig besitzt diese Eigenschaft den Wert `True`. Wird sie auf `False` gesetzt, wird der Button nicht angezeigt und kann weder per Maus noch per Tastatur verwendet werden.

```powershell
$button.Visible = $false
```

Die Eigenschaft eignet sich insbesondere, um Bedienelemente abhängig vom Programmzustand ein- oder auszublenden.

```powershell
$button.Visible = $userIsAdmin
```

</details>---

## **Methoden**


<table id="bkmrk-methode-beschreibung"><thead><tr><th>Methode</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`PerformClick()`</td><td>Löst das `Click`-Event programmgesteuert aus.</td></tr><tr><td>`Select()`</td><td>Versucht, den Button auszuwählen.</td></tr><tr><td>`Focus()`</td><td>Versucht, den Tastaturfokus auf den Button zu setzen.</td></tr><tr><td>`BringToFront()`</td><td>Bringt den Button innerhalb seines Parent-Containers in die vorderste Ebene.</td></tr><tr><td>`SendToBack()`</td><td>Verschiebt den Button innerhalb seines Parent-Containers in die hinterste Ebene.</td></tr></tbody></table>

<details id="bkmrk-performclick%28%29-perfo"><summary>PerformClick()</summary>

#### **PerformClick()**

```powershell
$button.PerformClick()
```

---

**Beschreibung**

Die Methode `PerformClick()` löst programmgesteuert einen Klick auf den Button aus.   
Dabei wird das `Click`-Event genauso ausgelöst, als hätte der Benutzer den Button mit der Maus angeklickt. Dadurch kann dieselbe Programmlogik sowohl durch Benutzereingaben als auch durch Code ausgeführt werden.   
Die Methode führt den Klick nur aus, wenn der Button aktiviert (`Enabled = $true`) und sichtbar (`Visible = $true`) ist.

---

**Rückgabe**

Keine Rückgabe `System.Void`

---

**Beispiel**

```powershell
$button.Add_Click({
    Write-Host "Button wurde geklickt."
})

# Klick per Code auslösen
$button.PerformClick()
```

</details><details id="bkmrk-select%28%29-select%28%29-%24b"><summary>Select()</summary>

#### **Select()**

```powershell
$button.Select()
```

---

**Beschreibung**

Die Methode `Select()` versucht, den Eingabefokus auf den Button zu setzen.   
Der Button erhält den Fokus jedoch nur, wenn er aktiviert (`Enabled = $true`), sichtbar (`Visible = $true`) und innerhalb seines Parent-Containers auswählbar ist.   
Nach erfolgreichem Aufruf kann der Button beispielsweise direkt über die Leertaste oder Eingabetaste ausgelöst werden.

---

**Rückgabe**

Keine Rückgabe `System.Void`

---

**Beispiel**

```powershell
$button.Select()
```

</details><details id="bkmrk-focus%28%29-focus%28%29-%24but"><summary>Focus()</summary>

#### **Focus()**

```powershell
$button.Focus()
```

---

**Beschreibung**

Die Methode `Focus()` versucht, den Tastaturfokus auf den Button zu setzen.   
Im Gegensatz zu `Select()` liefert die Methode einen Rückgabewert, anhand dessen überprüft werden kann, ob das Setzen des Fokus erfolgreich war.   
Die Methode schlägt beispielsweise fehl, wenn der Button deaktiviert oder nicht sichtbar ist.

---

**Rückgabe**

Gibt `True` zurück, wenn der Fokus erfolgreich gesetzt werden konnte, andernfalls `False`.

Rückgabetyp: `System.Boolean`

---

**Beispiel**

```powershell
if ($button.Focus()) {
    Write-Host "Button besitzt jetzt den Fokus."
}
else {
    Write-Host "Fokus konnte nicht gesetzt werden."
}
```

</details><details id="bkmrk-bringtofront%28%29-bring"><summary>BringToFront()</summary>

#### **BringToFront()**

```powershell
$button.BringToFront()
```

---

**Beschreibung**Die Methode `BringToFront()` bringt den Button innerhalb seines Parent-Containers in die vorderste Ebene der Z-Reihenfolge.

Dies ist insbesondere relevant, wenn sich mehrere Controls überlappen. Der Button wird dadurch vor anderen Controls desselben Parent-Containers dargestellt.

Die Methode verändert weder die Position (`Location`) noch die Größe (`Size`) des Buttons.

---

**Rückgabe**Keine Rückgabe `System.Void`

---

**Beispiel**```powershell
$button.BringToFront()
```

</details><details id="bkmrk-sendtoback%28%29-sendtob"><summary>SendToBack()</summary>

#### **SendToBack()**

```powershell
$button.SendToBack()
```

---

 **Beschreibung**

Die Methode `SendToBack()` verschiebt den Button innerhalb seines Parent-Containers in die hinterste Ebene der Z-Reihenfolge.

Dies ist insbesondere relevant, wenn sich mehrere Controls überlappen. Der Button wird dadurch hinter anderen Controls desselben Parent-Containers dargestellt.

Die Methode verändert weder die Position (`Location`) noch die Größe (`Size`) des Buttons.

---

**Rückgabe**Keine Rückgabe `System.Void`

---

**Beispiel**```powershell
$button.SendToBack()
```

</details>---

## **Events**

<table id="bkmrk-event-beschreibung-c"><thead><tr><th>Event</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`Click`</td><td>Wird ausgelöst, wenn der Button angeklickt wird.</td></tr><tr><td>`DoubleClick`</td><td>Wird bei einem Doppelklick ausgelöst.</td></tr><tr><td>`MouseClick`</td><td>Reagiert auf einen Mausklick und liefert Informationen über die Maustaste.</td></tr><tr><td>`MouseDown`</td><td>Wird beim Drücken einer Maustaste ausgelöst.</td></tr><tr><td>`MouseUp`</td><td>Wird beim Loslassen einer Maustaste ausgelöst.</td></tr><tr><td>`MouseEnter`</td><td>Wird ausgelöst, wenn der Mauszeiger den Button betritt.</td></tr><tr><td>`MouseLeave`</td><td>Wird ausgelöst, wenn der Mauszeiger den Button verlässt.</td></tr><tr><td>`MouseMove`</td><td>Wird während der Mausbewegung über dem Button ausgelöst.</td></tr><tr><td>`GotFocus`</td><td>Wird ausgelöst, wenn der Button den Tastaturfokus erhält.</td></tr><tr><td>`LostFocus`</td><td>Wird ausgelöst, wenn der Button den Tastaturfokus verliert.</td></tr><tr><td>`KeyDown`</td><td>Wird beim Drücken einer Taste ausgelöst.</td></tr><tr><td>`KeyPress`</td><td>Wird ausgelöst, wenn ein druckbares Zeichen eingegeben wird.</td></tr><tr><td>`KeyUp`</td><td>Wird beim Loslassen einer Taste ausgelöst.</td></tr></tbody></table>

<details id="bkmrk-click-click-das-clic"><summary>Click</summary>

#### **Click**

Das `Click`-Event wird ausgelöst, wenn der Benutzer den Button anklickt oder dieser programmgesteuert über `PerformClick()` ausgelöst wird.

Dies ist das am häufigsten verwendete Event eines Buttons und dient üblicherweise zum Ausführen einer Aktion.

---

**Beispiel**

```powershell
$button.Add_Click({
    Write-Host "Speichern..."
})
```

</details><details id="bkmrk-doubleclick-doublecl"><summary>DoubleClick</summary>

#### **DoubleClick**

Das `DoubleClick`-Event wird ausgelöst, wenn der Benutzer den Button doppelt anklickt.

Da Buttons normalerweise bereits auf den ersten Klick reagieren, wird dieses Event nur selten verwendet.

---

**Beispiel**

```powershell
$button.Add_DoubleClick({
    Write-Host "Doppelklick"
})
```

</details><details id="bkmrk-mouseclick-mouseclic"><summary>MouseClick</summary>

#### **MouseClick**

Das `MouseClick`-Event wird ausgelöst, wenn der Benutzer den Button mit einer Maustaste anklickt.

Im Gegensatz zum `Click`-Event stehen zusätzliche Informationen zur verwendeten Maustaste sowie zur Mausposition zur Verfügung.

---

<div class="group TyagGW_tableContainer"><div class="TyagGW_tableWrapper flex flex-col-reverse w-fit" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" style="width:100%;"><thead><tr><th class="last:pe-10" style="width:11.8648%;">Eigenschaft</th><th class="last:pe-10" style="width:14.0932%;">Typ</th><th class="last:pe-10" style="width:74.042%;">Beschreibung</th></tr></thead><tbody><tr><td style="width:11.8648%;">`Button`</td><td style="width:14.0932%;">`MouseButtons`</td><td style="width:74.042%;">Gibt an, welche Maustaste gedrückt wurde (`Left`, `Right`, `Middle`, `XButton1`, `XButton2`).</td></tr><tr><td style="width:11.8648%;">`Clicks`</td><td style="width:14.0932%;">`Int32`</td><td style="width:74.042%;">Anzahl der aufeinanderfolgenden Mausklicks.</td></tr><tr><td style="width:11.8648%;">`X`</td><td style="width:14.0932%;">`Int32`</td><td style="width:74.042%;">X-Koordinate des Mauszeigers relativ zum Button.</td></tr><tr><td style="width:11.8648%;">`Y`</td><td style="width:14.0932%;">`Int32`</td><td style="width:74.042%;">Y-Koordinate des Mauszeigers relativ zum Button.</td></tr><tr><td style="width:11.8648%;">`Location`</td><td style="width:14.0932%;">`Point`</td><td style="width:74.042%;">Mausposition als `Point` (`X` und `Y` zusammengefasst).</td></tr><tr><td style="width:11.8648%;">`Delta`</td><td style="width:14.0932%;">`Int32`</td><td style="width:74.042%;">Wert des Mausrads. Beim `MouseClick` normalerweise `0`. Relevant vor allem beim `MouseWheel`-Event.</td></tr></tbody></table>

</div></div>### Beispiel

```powershell
$button.Add_MouseClick({
    param($sender, $e)

    Write-Host "Taste    : $($e.Button)"
    Write-Host "Klicks   : $($e.Clicks)"
    Write-Host "X        : $($e.X)"
    Write-Host "Y        : $($e.Y)"
    Write-Host "Position : $($e.Location)"
})
```

### Ausgabe

```powershell
Taste    : Left
Klicks   : 1
X        : 84
Y        : 17
Position : {X=84,Y=17}
```

---

```powershell
$button.Add_MouseClick({
    param($sender, $e)

    Write-Host $e.Button
})
```

</details><details id="bkmrk-mousedown-mousedown-"><summary>MouseDown</summary>

#### **MouseDown**

Das `MouseDown`-Event wird ausgelöst, sobald der Benutzer eine Maustaste auf dem Button drückt.

Dieses Event eignet sich beispielsweise zum Starten von Drag-and-Drop-Operationen oder zum Erfassen der gedrückten Maustaste.

---

**Beispiel**

```powershell
$button.Add_MouseDown({
    param($sender, $e)

    Write-Host "Taste gedrückt."
})
```

</details><details id="bkmrk-mouseup-mouseup-das-"><summary>MouseUp</summary>

#### **MouseUp**

Das `MouseUp`-Event wird ausgelöst, sobald eine gedrückte Maustaste wieder losgelassen wird.

---

**Beispiel**

```powershell
$button.Add_MouseUp({
    Write-Host "Taste losgelassen."
})
```

</details><details id="bkmrk-mouseenter-mouseente"><summary>MouseEnter</summary>

#### **MouseEnter**

Das `MouseEnter`-Event wird ausgelöst, wenn sich der Mauszeiger erstmals über dem Button befindet.

Es wird häufig verwendet, um beispielsweise Informationen einzublenden oder das Aussehen eines Controls zu verändern.

---

**Beispiel**

```powershell
$button.Add_MouseEnter({
    $button.BackColor = "LightBlue"
})
```

</details><details id="bkmrk-mouseleave-mouseleav"><summary>MouseLeave</summary>

#### **MouseLeave**

Das `MouseLeave`-Event wird ausgelöst, wenn der Mauszeiger den Button wieder verlässt.

---

**Beispiel**

```powershell
$button.Add_MouseLeave({
    $button.BackColor = "White"
})
```

</details><details id="bkmrk-mousemove-mousemove-"><summary>MouseMove</summary>

#### **MouseMove**

Das `MouseMove`-Event wird fortlaufend ausgelöst, während sich der Mauszeiger innerhalb des Buttons bewegt.

Über die Ereignisparameter können die aktuellen Mauskoordinaten abgefragt werden.

---

**Beispiel**

```powershell
$button.Add_MouseMove({
    param($sender, $e)

    Write-Host "$($e.X), $($e.Y)"
})
```

</details><details id="bkmrk-gotfocus-gotfocus-da"><summary>GotFocus</summary>

#### **GotFocus**

Das `GotFocus`-Event wird ausgelöst, sobald der Button den Tastaturfokus erhält.

---

**Beispiel**

```powershell
$button.Add_GotFocus({
    Write-Host "Button besitzt den Fokus."
})
```

</details><details id="bkmrk-lostfocus-lostfocus-"><summary>LostFocus</summary>

#### **LostFocus**

Das `LostFocus`-Event wird ausgelöst, wenn der Button den Tastaturfokus verliert.

---

**Beispiel**

```powershell
$button.Add_LostFocus({
    Write-Host "Fokus verloren."
})
```

</details><details id="bkmrk-keydown-keydown-das-"><summary>KeyDown</summary>

#### **KeyDown**

Das `KeyDown`-Event wird ausgelöst, sobald eine Taste gedrückt wird, während der Button den Fokus besitzt.

---

**Beispiel**

```powershell
$button.Add_KeyDown({
    param($sender, $e)

    if ($e.KeyCode -eq "Enter") {
        Write-Host "Enter"
    }
})
```

</details><details id="bkmrk-keypress-keypress-da"><summary>KeyPress</summary>

#### **KeyPress**

Das `KeyPress`-Event wird ausgelöst, wenn ein druckbares Zeichen eingegeben wird.

Es eignet sich insbesondere zur Verarbeitung einzelner Zeichen.

---

**Beispiel**

```powershell
$button.Add_KeyPress({
    param($sender, $e)

    Write-Host $e.KeyChar
})
```

</details><details id="bkmrk-keyup-keyup-das-keyu"><summary>KeyUp</summary>

#### **KeyUp**

Das `KeyUp`-Event wird ausgelöst, sobald eine gedrückte Taste wieder losgelassen wird.

---

**Beispiel**

```powershell
$button.Add_KeyUp({
    Write-Host "Taste losgelassen."
})
```

</details>---

## **Tipps &amp; Tricks**

#### Standard-Button eines Dialogs festlegen

Über die Eigenschaft `AcceptButton` eines Formulars kann festgelegt werden, welcher Button beim Drücken der **Eingabetaste** automatisch ausgelöst wird.

```powershell
$form.AcceptButton = $button
```

#### Abbrechen-Button festlegen

Über die Eigenschaft `CancelButton` kann ein Button festgelegt werden, der beim Drücken der **Esc-Taste** ausgelöst wird.

```powershell
$form.CancelButton = $cancelButton

```

#### Eigenes Icon links neben dem Text anzeigen

```powershell
$button.Image = [System.Drawing.Image]::FromFile("Save.png")
$button.ImageAlign = "MiddleLeft"
$button.TextImageRelation = "ImageBeforeText"
$button.Text = "Speichern"
```

#### Button farbig darstellen

Damit `BackColor` verwendet wird, muss die Windows-Designfarbe deaktiviert werden.

```powershell
$button.UseVisualStyleBackColor = $false
$button.BackColor = "RoyalBlue"
$button.ForeColor = "White"

```

# Label

Ein `Label` ist ein Steuerelement zur **Anzeige von Text und optionalen Bildern**.

Im Gegensatz zu interaktiven Controls wie `Button` oder `TextBox` dient ein `Label` hauptsächlich dazu, Informationen, Beschriftungen oder Hinweise innerhalb einer Benutzeroberfläche darzustellen.

Ein `Label` kann jedoch auch auf Mausereignisse reagieren und beispielsweise über das `Click`-Event als anklickbares Element verwendet werden.

---

# Grundlagen

Ein `Label` wird hauptsächlich verwendet, um Informationen innerhalb eines Formulars darzustellen.

- `Label` → zeigt Informationen oder Beschriftungen an
- `Button` → führt eine Aktion aus
- `TextBox` → ermöglicht Texteingaben

---

#### Label erstellen

```powershell
# Klassisch
$label = New-Object System.Windows.Forms.Label

# .NET-Style
$label = [System.Windows.Forms.Label]::new()

```

---

#### Label hinzufügen

Ein `Label` wird wie jedes andere Control der `Controls`-Collection seines Parent-Containers hinzugefügt.

```powershell
$form.Controls.Add($label)

# oder

$tabPage.Controls.Add($label)

```

---

#### Text festlegen

Der sichtbare Inhalt eines Labels wird über die Eigenschaft `Text` festgelegt.

```powershell
$label.Text = "Benutzername:"

```

---

# Eigenschaften

<table id="bkmrk-eigenschaft-beschrei"><thead><tr><th>Eigenschaft</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`AutoEllipsis`</td><td>Zeigt bei nicht vollständig darstellbarem Text automatisch `...` an.</td></tr><tr><td>`AutoSize`</td><td>Passt die Größe des Labels automatisch an dessen Inhalt an.</td></tr><tr><td>`BackColor`</td><td>Legt die Hintergrundfarbe des Labels fest.</td></tr><tr><td>`BorderStyle`</td><td>Bestimmt, ob und wie ein Rahmen um das Label dargestellt wird.</td></tr><tr><td>`Cursor`</td><td>Legt den Mauszeiger fest, wenn sich der Mauszeiger über dem Label befindet.</td></tr><tr><td>`Dock`</td><td>Dockt das Label an einer Seite seines Parent-Containers an.</td></tr><tr><td>`Enabled`</td><td>Legt fest, ob das Label aktiviert dargestellt wird und auf Eingaben reagieren kann.</td></tr><tr><td>`FlatStyle`</td><td>Bestimmt die Darstellungsart des Labels.</td></tr><tr><td>`Font`</td><td>Legt Schriftart, -größe und -stil fest.</td></tr><tr><td>`ForeColor`</td><td>Legt die Textfarbe fest.</td></tr><tr><td>`Image`</td><td>Zeigt ein Bild im Label an.</td></tr><tr><td>`ImageAlign`</td><td>Bestimmt die Position des Bildes innerhalb des Labels.</td></tr><tr><td>`ImageIndex`</td><td>Wählt ein Bild anhand seines Indexes aus der `ImageList` aus.</td></tr><tr><td>`ImageKey`</td><td>Wählt ein Bild anhand seines Namens aus der `ImageList` aus.</td></tr><tr><td>`ImageList`</td><td>Legt die Bildersammlung für das Label fest.</td></tr><tr><td>`Location`</td><td>Bestimmt die Position des Labels im Parent-Container.</td></tr><tr><td>`Margin`</td><td>Legt den äußeren Abstand zu benachbarten Controls fest.</td></tr><tr><td>`MaximumSize`</td><td>Definiert die maximal zulässige Größe.</td></tr><tr><td>`MinimumSize`</td><td>Definiert die minimal zulässige Größe.</td></tr><tr><td>`Name`</td><td>Legt den internen Namen des Labels fest.</td></tr><tr><td>`Padding`</td><td>Legt den Innenabstand zwischen Rand und Inhalt fest.</td></tr><tr><td>`Size`</td><td>Bestimmt Breite und Höhe des Labels.</td></tr><tr><td>`TabIndex`</td><td>Legt die Reihenfolge der Tabulator-Navigation fest.</td></tr><tr><td>`TabStop`</td><td>Legt fest, ob das Label per Tabulator fokussiert werden kann.</td></tr><tr><td>`Text`</td><td>Bestimmt den sichtbaren Text des Labels.</td></tr><tr><td>`TextAlign`</td><td>Legt die Position des Textes innerhalb des Labels fest.</td></tr><tr><td>`UseCompatibleTextRendering`</td><td>Bestimmt, ob für die Textdarstellung die ältere GDI+- oder die neuere GDI-Textdarstellung verwendet wird.</td></tr><tr><td>`UseMnemonic`</td><td>Aktiviert Tastenkombinationen über `&` im Text.</td></tr><tr><td>`Visible`</td><td>Legt fest, ob das Label sichtbar ist.</td></tr></tbody></table>

---

<details id="bkmrk-autoellipsis-autoell"><summary>AutoEllipsis</summary>

#### **AutoEllipsis**

**Typ** = `[System.Boolean]`

Der Wert von `AutoEllipsis` legt fest, ob zu langer Text automatisch mit `...` gekürzt werden soll, wenn dieser nicht vollständig dargestellt werden kann.

Standardmäßig ist diese Eigenschaft auf `False` gesetzt.

```powershell
$label.AutoEllipsis = $true

```

> 💡 **Hinweis** `AutoEllipsis` ist insbesondere dann sinnvoll, wenn die Größe des Labels begrenzt ist und der vollständige Text nicht angezeigt werden kann.

</details><details id="bkmrk-autosize-autosize-ty"><summary>AutoSize</summary>

#### **AutoSize**

**Typ** = `[System.Boolean]`

Der Wert von `AutoSize` legt fest, ob sich die Größe des Labels automatisch an dessen Inhalt anpasst.

Beim `Label` ist `AutoSize` standardmäßig auf `True` gesetzt.

Dadurch wird die Größe automatisch anhand des enthaltenen Textes beziehungsweise Bildes bestimmt.

```powershell
$label.AutoSize = $true

```

Soll das Label eine feste Größe besitzen, kann `AutoSize` deaktiviert werden.

```powershell
$label.AutoSize = $false
$label.Size = "200, 40"

```

</details><details id="bkmrk-backcolor-backcolor-"><summary>BackColor</summary>

#### **BackColor**

**Typ** = `[System.Drawing.Color]`

Der Wert von `BackColor` legt die Hintergrundfarbe des Labels fest.

```powershell
$label.BackColor = "LightBlue"

```

Standardmäßig übernimmt das Label die Hintergrundfarbe seines Parent-Controls beziehungsweise die von Windows vorgegebene Standardfarbe.

</details><details id="bkmrk-borderstyle-borderst"><summary>BorderStyle</summary>

#### **BorderStyle**

**Typ** = `[System.Windows.Forms.BorderStyle]`

Der Wert von `BorderStyle` bestimmt, ob und wie ein Rahmen um das Label dargestellt wird.

Folgende Werte stehen zur Verfügung:

- **None** → kein Rahmen
- **FixedSingle** → einfacher Rahmen
- **Fixed3D** → dreidimensionaler Rahmen

Standardmäßig besitzt diese Eigenschaft den Wert `None`.

```powershell
$label.BorderStyle = "FixedSingle"

```

</details><details id="bkmrk-cursor-cursor-typ-%3D-"><summary>Cursor</summary>

#### **Cursor**

**Typ** = `[System.Windows.Forms.Cursor]`

Der Wert von `Cursor` legt fest, welcher Mauszeiger angezeigt wird, wenn sich der Mauszeiger über dem Label befindet.

```powershell
$label.Cursor = [System.Windows.Forms.Cursors]::Hand

```

Dies kann beispielsweise verwendet werden, wenn das Label wie ein anklickbarer Link verwendet wird.

</details><details id="bkmrk-dock-dock-typ-%3D-%5Bsys"><summary>Dock</summary>

#### **Dock**

**Typ** = `[System.Windows.Forms.DockStyle]`

Der Wert von `Dock` legt fest, an welcher Seite seines Parent-Containers das Label angedockt wird.

Standardmäßig besitzt diese Eigenschaft den Wert `None`.

```powershell
$label.Dock = "Top"

```

Alternativ kann das Label mit `Fill` den gesamten verfügbaren Bereich einnehmen.

```powershell
$label.Dock = "Fill"

```

Im Gegensatz zu `Anchor` übernimmt `Dock` sowohl die Positionierung als auch die Größenanpassung des Controls.

</details><details id="bkmrk-enabled-enabled-typ-"><summary>Enabled</summary>

#### **Enabled**

**Typ** = `[System.Boolean]`

Der Wert von `Enabled` legt fest, ob das Label aktiviert ist.

Standardmäßig besitzt diese Eigenschaft den Wert `True`.

Wird `Enabled` auf `False` gesetzt, wird das Label deaktiviert dargestellt und reagiert nicht mehr auf Eingaben.

```powershell
$label.Enabled = $false

```

> 💡 **Hinweis** Bei einem gewöhnlichen Label betrifft `Enabled` hauptsächlich die Darstellung. Ein Label ist standardmäßig ohnehin nicht über die Tabulator-Navigation fokussierbar.

</details><details id="bkmrk-flatstyle-flatstyle-"><summary>FlatStyle</summary>

#### **FlatStyle**

**Typ** = `[System.Windows.Forms.FlatStyle]`

Der Wert von `FlatStyle` bestimmt die Darstellungsart des Labels.

Folgende Werte stehen zur Verfügung:

- **Flat** → flache Darstellung
- **Popup** → flache Darstellung mit Hervorhebung bei Interaktion
- **Standard** → Standarddarstellung
- **System** → Darstellung durch Windows

```powershell
$label.FlatStyle = "Flat"

```

</details><details id="bkmrk-font-font-typ-%3D-%5Bsys"><summary>Font</summary>

#### **Font**

**Typ** = `[System.Drawing.Font]`

Der Wert von `Font` legt die Schriftart fest, mit der der Text des Labels dargestellt wird.

Änderungen an dieser Eigenschaft beeinflussen Schriftart, Schriftgröße und Schriftstil.

```powershell
$label.Font = [System.Drawing.Font]::new(
    "Segoe UI",
    10,
    "Bold"
)

```

</details><details id="bkmrk-forecolor-forecolor-"><summary>ForeColor</summary>

#### **ForeColor**

**Typ** = `[System.Drawing.Color]`

Der Wert von `ForeColor` legt die Farbe fest, mit der der Text des Labels dargestellt wird.

```powershell
$label.ForeColor = "White"

```

</details><details id="bkmrk-image-image-typ-%3D-%5Bs"><summary>Image</summary>

#### **Image**

**Typ** = `[System.Drawing.Image]`

Der Wert von `Image` legt das Bild fest, das im Label angezeigt werden soll.

```powershell
$label.Image = [System.Drawing.Image]::FromFile(
    "C:\Icons\Info.png"
)

```

Ist gleichzeitig Text vorhanden, bestimmt `TextAlign` beziehungsweise `ImageAlign`, wie die Inhalte innerhalb des Labels positioniert werden.

</details><details id="bkmrk-imagealign-imagealig"><summary>ImageAlign</summary>

#### **ImageAlign**

**Typ** = `[System.Drawing.ContentAlignment]`

Der Wert von `ImageAlign` legt fest, an welcher Position das Bild innerhalb des Labels dargestellt wird.

```powershell
$label.ImageAlign = "MiddleCenter"

```

</details><details id="bkmrk-imageindex-imageinde"><summary>ImageIndex</summary>

#### **ImageIndex**

**Typ** = `[System.Int32]`

Der Wert von `ImageIndex` bestimmt den Index des Bildes innerhalb der zugewiesenen `ImageList`.

Standardmäßig ist kein Bild ausgewählt.

```powershell
$label.ImageList = $imageList
$label.ImageIndex = 0

```

> 💡 **Hinweis** `ImageIndex` und `ImageKey` dienen demselben Zweck. Es sollte immer nur eine der beiden Eigenschaften verwendet werden.

</details><details id="bkmrk-imagekey-imagekey-ty"><summary>ImageKey</summary>

#### **ImageKey**

**Typ** = `[System.String]`

Der Wert von `ImageKey` legt den Namen eines Bildes innerhalb der zugewiesenen `ImageList` fest.

```powershell
$label.ImageList = $imageList
$label.ImageKey = "Info"

```

Im Gegensatz zu `ImageIndex` erfolgt die Auswahl über den Namen des Bildes.

</details><details id="bkmrk-imagelist-imagelist-"><summary>ImageList</summary>

#### **ImageList**

**Typ** = `[System.Windows.Forms.ImageList]`

Der Wert von `ImageList` legt die Bildersammlung fest, aus der das Label ein Bild beziehen kann.

Welche Grafik verwendet wird, wird anschließend über `ImageIndex` oder `ImageKey` bestimmt.

```powershell
$label.ImageList = $imageList
$label.ImageIndex = 0

```

</details><details id="bkmrk-location-location-ty"><summary>Location</summary>

#### **Location**

**Typ** = `[System.Drawing.Point]`

Der Wert von `Location` legt die Position des Labels innerhalb seines Parent-Containers fest.

Die Position wird über die X- und Y-Koordinate relativ zum Parent-Control angegeben.

```powershell
$label.Location = "20, 40"

```

> 💡 **Hinweis** Wird das Label durch einen Layout-Container oder `Dock` positioniert, wird `Location` vom Layoutsystem verwaltet.

</details><details id="bkmrk-margin-margin-typ-%3D-"><summary>Margin</summary>

#### **Margin**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Margin` legt den äußeren Abstand des Labels zu benachbarten Controls fest.

Die Eigenschaft wird insbesondere von Layout-Containern wie `FlowLayoutPanel` oder `TableLayoutPanel` berücksichtigt.

```powershell
$label.Margin = [System.Windows.Forms.Padding]::new(10)

```

</details><details id="bkmrk-maximumsize-maximums"><summary>MaximumSize</summary>

#### **MaximumSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `MaximumSize` legt die maximal zulässige Größe des Labels fest.

Standardmäßig besitzt diese Eigenschaft den Wert `(0,0)`. Dadurch existiert keine Größenbegrenzung.

```powershell
$label.MaximumSize = "300, 100"

```

</details><details id="bkmrk-minimumsize-minimums"><summary>MinimumSize</summary>

#### **MinimumSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `MinimumSize` legt die minimal zulässige Größe des Labels fest.

```powershell
$label.MinimumSize = "100, 25"

```

</details><details id="bkmrk-name-name-typ-%3D-%5Bsys"><summary>Name</summary>

#### **Name**

**Typ** = `[System.String]`

Der Wert von `Name` legt den internen Namen des Labels fest.

Der Name dient ausschließlich der Identifikation innerhalb des Programms und wird dem Benutzer nicht angezeigt.

```powershell
$label.Name = "lblUsername"

```

</details><details id="bkmrk-padding-padding-typ-"><summary>Padding</summary>

#### **Padding**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Padding` legt den Innenabstand zwischen dem Rand des Labels und dessen Inhalt fest.

```powershell
$label.Padding = [System.Windows.Forms.Padding]::new(8)

```

</details><details id="bkmrk-size-size-typ-%3D-%5Bsys"><summary>Size</summary>

#### **Size**

**Typ** = `[System.Drawing.Size]`

Der Wert von `Size` legt die Breite und Höhe des Labels fest.

```powershell
$label.Size = "200, 35"

```

Ist `AutoSize` aktiviert, kann die Größe automatisch anhand des Inhalts angepasst werden.

</details><details id="bkmrk-tabindex-tabindex-ty"><summary>TabIndex</summary>

#### **TabIndex**

**Typ** = `[System.Int32]`

Der Wert von `TabIndex` legt die Reihenfolge fest, in der das Label den Fokus erhält, wenn der Benutzer die **Tabulator-Taste** betätigt.

Standardmäßig besitzt ein Label einen `TabIndex`, obwohl es normalerweise nicht über die Tabulator-Navigation fokussiert werden kann.

```powershell
$label.TabIndex = 2

```

> 💡 **Hinweis** `TabIndex` wird beim Label erst relevant, wenn `TabStop` auf `True` gesetzt wird.

</details><details id="bkmrk-tabstop-tabstop-typ-"><summary>TabStop</summary>

#### **TabStop**

**Typ** = `[System.Boolean]`

Der Wert von `TabStop` legt fest, ob das Label über die **Tabulator-Taste** den Fokus erhalten kann.

Beim `Label` ist diese Eigenschaft standardmäßig auf `False` gesetzt.

```powershell
$label.TabStop = $true

```

Dadurch kann das Label Teil der Tabulator-Navigation werden.

> 💡 **Hinweis** Ein gewöhnliches Label ist kein interaktives Eingabeelement. Deshalb ist `TabStop` standardmäßig deaktiviert.

</details><details id="bkmrk-text-text-typ-%3D-%5Bsys"><summary>Text</summary>

#### **Text**

**Typ** = `[System.String]`

Der Wert von `Text` legt den sichtbaren Text des Labels fest.

```powershell
$label.Text = "Benutzername:"

```

Standardmäßig besitzt diese Eigenschaft den Wert `""` (leerer String).

</details><details id="bkmrk-textalign-textalign-"><summary>TextAlign</summary>

#### **TextAlign**

**Typ** = `[System.Drawing.ContentAlignment]`

Der Wert von `TextAlign` legt fest, an welcher Position der Text innerhalb des Labels dargestellt wird.

```powershell
$label.TextAlign = "MiddleCenter"

```

Dadurch wird der Text sowohl horizontal als auch vertikal zentriert.

</details><details id="bkmrk-usecompatibletextren"><summary>UseCompatibleTextRendering</summary>

#### **UseCompatibleTextRendering**

**Typ** = `[System.Boolean]`

Der Wert von `UseCompatibleTextRendering` bestimmt, welche Textdarstellung für das Label verwendet wird.

Bei `False` wird die neuere GDI-basierte Textdarstellung verwendet. Bei `True` wird die ältere GDI+-basierte Darstellung verwendet.

```powershell
$label.UseCompatibleTextRendering = $true

```

Die Eigenschaft ist hauptsächlich für Kompatibilität mit älteren Anwendungen relevant.

> 💡 **Hinweis** In den meisten Fällen kann der Standardwert verwendet werden. Die Eigenschaft wird insbesondere dann interessant, wenn Unterschiede bei der Textdarstellung, beispielsweise bei Zeilenumbruch oder Schriftmessung, auftreten.

</details><details id="bkmrk-usemnemonic-usemnemo"><summary>UseMnemonic</summary>

#### **UseMnemonic**

**Typ** = `[System.Boolean]`

Der Wert von `UseMnemonic` legt fest, ob das Zeichen `&` im Text zur Definition eines **Tastaturkürzels** verwendet wird.

Ist die Eigenschaft aktiviert, wird das Zeichen direkt vor einem Buchstaben als Kennzeichnung für eine Mnemonic-Taste interpretiert.

```powershell
$label.Text = "&Name:"
$label.UseMnemonic = $true

```

Das `N` kann dadurch als Zugriffstaste verwendet werden.

Soll das Zeichen `&` tatsächlich angezeigt werden, kann es durch `&&` maskiert werden.

```powershell
$label.Text = "Speichern && Beenden"

```

</details><details id="bkmrk-visible-visible-typ-"><summary>Visible</summary>

#### **Visible**

**Typ** = `[System.Boolean]`

Der Wert von `Visible` legt fest, ob das Label sichtbar ist.

Standardmäßig besitzt diese Eigenschaft den Wert `True`.

```powershell
$label.Visible = $false

```

Wird die Eigenschaft auf `False` gesetzt, wird das Label ausgeblendet.

</details>---

# Events

Ein `Label` kann auf verschiedene Ereignisse reagieren. Besonders häufig werden Mausereignisse verwendet, wenn das Label wie ein anklickbares Element eingesetzt wird.

<table id="bkmrk-event-beschreibung-c"><thead><tr><th>Event</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`Click`</td><td>Das Label wurde angeklickt.</td></tr><tr><td>`DoubleClick`</td><td>Das Label wurde doppelt angeklickt.</td></tr><tr><td>`MouseEnter`</td><td>Der Mauszeiger befindet sich über dem Label.</td></tr><tr><td>`MouseLeave`</td><td>Der Mauszeiger verlässt das Label.</td></tr><tr><td>`MouseDown`</td><td>Eine Maustaste wurde über dem Label gedrückt.</td></tr><tr><td>`MouseUp`</td><td>Eine Maustaste wurde über dem Label losgelassen.</td></tr><tr><td>`TextChanged`</td><td>Der Text des Labels wurde geändert.</td></tr><tr><td>`VisibleChanged`</td><td>Die Sichtbarkeit des Labels wurde geändert.</td></tr><tr><td>`EnabledChanged`</td><td>Der Aktivierungszustand des Labels wurde geändert.</td></tr><tr><td>`FontChanged`</td><td>Die Schriftart des Labels wurde geändert.</td></tr><tr><td>`ForeColorChanged`</td><td>Die Textfarbe des Labels wurde geändert.</td></tr><tr><td>`SizeChanged`</td><td>Die Größe des Labels wurde geändert.</td></tr></tbody></table>

### Event hinzufügen

Events werden beim `Label` mit dem Präfix `Add_` hinzugefügt.

```powershell
$label.Add_Click({
    param($sender, $e)

    Write-Host "Label wurde geklickt."
})

```

### Event entfernen

Ein zuvor hinzugefügtes Event kann über das entsprechende `Remove_`-Präfix wieder entfernt werden.

```powershell
$label.Remove_Click($event)

```

---

# Tipps

#### Label automatisch an den Text anpassen

Mit `AutoSize` kann die Größe automatisch an den Inhalt angepasst werden.

```powershell
$label.AutoSize = $true

```

---

# Typische Verwendung

Ein `Label` wird häufig für folgende Aufgaben verwendet:

- Beschriftungen von Eingabefeldern
- Überschriften
- Statusinformationen
- Hinweise und Hilfetexte
- Anzeigen von Werten
- klickbare Text-Elemente
- Anzeige von Icons oder Bildern

Ein typisches Formular kann beispielsweise so aufgebaut sein:

```powershell
$label = [System.Windows.Forms.Label]::new()

$label.Text      = "Benutzername:"
$label.AutoSize  = $true
$label.Location  = "20, 20"

$form.Controls.Add($label)

```

---

# Label als klickbares Element

Obwohl ein `Label` hauptsächlich zur Darstellung von Informationen dient, kann es auf Mausereignisse reagieren.

Dadurch kann es beispielsweise als einfacher Link oder als Schaltfläche für kleinere Aktionen verwendet werden.

```powershell
$label.Text   = "Über das Programm"
$label.Cursor = [System.Windows.Forms.Cursors]::Hand

$label.Add_Click({
    Show-About
})

```

Für komplexere Aktionen sollte jedoch weiterhin ein `Button` verwendet werden.

> 💡 **Hinweis** Ein `Label` besitzt zwar ein `Click`-Event, ist aber semantisch kein Button. Bei wichtigen oder häufig verwendeten Aktionen ist ein `Button` daher die bessere Wahl.

---

# Hinweise

- `Label` dient hauptsächlich zur **Darstellung von Informationen**.
- `AutoSize` ist beim `Label` standardmäßig aktiviert.
- `TabStop` ist beim `Label` standardmäßig deaktiviert.
- `TabIndex` ist vorhanden, wird aber erst relevant, wenn `TabStop` aktiviert wird.
- Über `Image`, `ImageList`, `ImageIndex` und `ImageKey` können Bilder angezeigt werden.
- Mit `TextAlign` kann der Text innerhalb des Labels positioniert werden.
- Über `Click` kann ein Label interaktiv gemacht werden.
- Für echte Benutzeraktionen sollte in der Regel ein `Button` verwendet werden.

```

Eine kleine Korrektur gegenüber meiner vorherigen Antwort ist dabei wichtig: **`TabIndex` und `TabStop` sind beim `Label` tatsächlich vorhanden, aber `TabStop` steht standardmäßig auf `False`**. Das ist für deine Doku die relevante Information, statt so zu tun, als wäre die bloße Existenz der beiden Properties schon praktisch bedeutungsvoll. WinForms liebt solche geerbten Eigenschaften. :contentReference[oaicite:1]{index=1}

```

# RichTextBox

**Namespace:** `System.Windows.Forms`

<details id="bkmrk-properties-%2F-eigensc"><summary>Properties / Eigenschaften</summary>

- *Property – Standardwert*  
    Beschreibung oder Erläuterung der Eigenschaft

---

- **BackColor** – *SystemColors.Window*  
    Hintergrundfarbe der RichTextBox
- **BorderStyle** – *Fixed3D*  
    Rahmenstil (`None`, `FixedSingle`, `Fixed3D`)
- **Font** – *Standard-Systemfont*  
    Schriftart und -größe
- **ForeColor** – *SystemColors.WindowText*  
    Textfarbe
- **HideSelection** – *$true*  
    Steuert, ob der Text im nicht markierten Zustand verborgen wird
- **Text** – *""*  
    Der gesamte Text in der RichTextBox
- **WordWrap** – *$true*  
    Zeilenumbruch aktivieren/deaktivieren
- **Rtf** – *""*  
    Ruft den RTF-Inhalt der RichTextBox ab oder setzt ihn
- **Multiline** – *$true*  
    Zeigt Text auf mehreren Zeilen
- **SelectionAlignment** – *Left*  
    Ausrichtung des Textes in der aktuellen Auswahl (`Left`, `Center`, `Right`)
- **SelectionColor** – *SystemColors.HighlightText*  
    Farbe der ausgewählten Textstellen
- **SelectionFont** – *Standard-Schrift*  
    Schriftart der Auswahl
- **SelectionBackColor** – *SystemColors.Highlight*  
    Hintergrundfarbe der Auswahl
- **SelectionLength** – 0  
    Länge der aktuellen Auswahl
- **SelectionStart** – 0  
    Der Startindex der aktuellen Auswahl
- **TextChanged** – *$false*  
    Event wird ausgelöst, wenn sich der Text ändert

</details>Die **RichTextBox** ist eine erweiterte Textbox, die es ermöglicht, formatierte Textinhalte darzustellen und zu bearbeiten. Sie unterstützt RTF (Rich Text Format) sowie einfache Textformate.

---

#### **Erstellen**

```powershell
# Erstellen
$richTextBox = New-Object System.Windows.Forms.RichTextBox
$richTextBoxNew = [System.Windows.Forms.RichTextBox]::new()

# Größe & Position
$richTextBox.Size = New-Object System.Drawing.Size(400, 200)
$richTextBox.Location = New-Object System.Drawing.Point(10,10)

# Text setzen
$richTextBox.Text = "Hallo, dies ist ein Testtext in der RichTextBox!"

# Formatierter Text (RTF)
$richTextBox.Rtf = "{\rtf1\ansi\ansicpg1252\uc1\pard\lang1031\f0\fs20 Hallo, \b dies ist ein \i Test \b0\i0 Text.\par}"

```

#### **📥 Werte auslesen**

```powershell
# Einfacher Text
$plainText = $richTextBox.Text

# RTF-Text
$rtfText = $richTextBox.Rtf

# Auswahl
$selectedText = $richTextBox.SelectedText
```

👉 **Unterschied:**  
`Text` gibt nur den normalen Text zurück, während `Rtf` den gesamten formatierten Text (inklusive Formatierung) liefert.

---

## <span>**Events -** *RichTextBox*</span>

#### <span>**TextChanged**</span>

Wird ausgelöst, wenn sich der Text in der RichTextBox ändert.

```Powershell
$richTextBox.Add_TextChanged({
Write-Host "Text hat sich geändert!"
})
```

---

#### <span>**SelectionChanged**</span>

Wenn der Benutzer die Auswahl ändert, wird dieses Event ausgelöst.

```Powershell
$richTextBox.Add_SelectionChanged({
Write-Host "Neue Auswahl: $($richTextBox.SelectedText)"
})
```

---

#### <span>**LinkClicked**</span>

Wenn der Benutzer auf einen Link klickt, wird dieses Event ausgelöst.

```powershell
$richTextBox.Add_LinkClicked({
param($sender, $e)
Write-Host "Link angeklickt: $($e.Link)"
})
```

---

## <span>**Tipps &amp; Tricks**</span>

#### **Formatierter Text**

```powershell
$richTextBox.SelectionColor = "Red"
$richTextBox.SelectionFont = New-Object System.Drawing.Font("Arial", 12, [System.Drawing.FontStyle]::Bold)

$richTextBox.AppendText(" Dies ist ein Text mit roter Schrift und fettem Arial.")
```

---

#### **RTF-Inhalt speichern**

```powershell
# RTF in Datei speichern
$richTextBox.SaveFile("C:\Pfad\zur\Datei.rtf", [System.Windows.Forms.RichTextBoxStreamType]::RichText)
```

---

#### **Hyperlinks hinzufügen**

```powershell
$richTextBox.AppendText("Hier klicken: ")
$richTextBox.InsertLink("https://www.example.com")
```

---

## ⚠️ Typische Stolperfallen

- **Text wird nicht formatiert**, aber du hast vergessen, den richtigen Stream (RTF vs. Text) zu verwenden.
- **Events feuern zu oft**: Achte darauf, dass du nicht zu viele Events auslöst. Besonders `TextChanged` ist gefährlich, weil es oft auch bei jeder kleinen Änderung feuert.

---

## 🧩 Best Practice

- Für einfache Textfelder immer die normale `TextBox` verwenden.
- Nutze `RichTextBox`, wenn du Formatierung und erweiterte Textoptionen brauchst.
- **RTF ist dein Freund**, wenn du komplexe Formatierungen brauchst – ansonsten geht auch normaler Text.

# CheckBox

**Namespace:** `System.Windows.Forms`

<details id="bkmrk-eigenschaften-%2F-prop"><summary>Eigenschaften / Propertys</summary>

- ***Property* – Standardwert**  
    Beschreibung oder Erläuterung der Eigenschaft

---

- **Appearance** – *Normal*  
    Darstellung der CheckBox  
    `Normal` = klassische Checkbox  
    `Button` = verhält sich wie ein Toggle-Button
- **AutoCheck** – *$true*  
    Ob die CheckBox ihren Zustand automatisch selbst ändert
- **Checked** – *$false*  
    Ob die CheckBox aktiviert ist
- **CheckState** – *Unchecked*  
    Zustand der CheckBox  
    (`Unchecked`, `Checked`, `Indeterminate`)
- **ThreeState** – *$false*  
    Erlaubt dritten Zustand (`Indeterminate`)
- **Text** – *""*  
    Angezeigter Text neben der Checkbox
- **TextAlign** – *MiddleLeft*  
    Ausrichtung des Textes
- **CheckAlign** – *MiddleLeft*  
    Position des Häkchens
- **FlatStyle** – *Standard*  
    Darstellung der Checkbox  
    (`Standard`, `Flat`, `Popup`, `System`)
- **AutoSize** – *$false*  
    Passt Größe automatisch an Inhalt an
- **Enabled** – *$true*  
    Aktiviert oder deaktiviert die CheckBox
- **Visible** – *$true*  
    Sichtbarkeit der CheckBox
- **Font** – *Standard-Systemfont*  
    Schriftart des Textes
- **ForeColor** – *ControlText*  
    Textfarbe
- **BackColor** – *Transparent*  
    Hintergrundfarbe
- **Dock** – *None*  
    Docking innerhalb des Containers
- **Anchor** – *(Top, Left)*  
    Verhalten bei Größenänderung des Containers
- **Location** – *(0,0)*  
    Position innerhalb des Containers
- **Size** – *(104,24 ungefähr)*  
    Größe der CheckBox
- **TabIndex** – 0  
    Reihenfolge beim Durchtabben
- **TabStop** – *$true*  
    Ob die CheckBox per TAB erreichbar ist

</details>---

Die **CheckBox** gehört zu diesen Controls, die harmlos aussehen… bis man plötzlich merkt, dass daran halbe UI-Logik hängt.

Denn technisch gesehen ist sie nicht einfach nur „an oder aus“.  
Sie ist oft ein kleiner Schalter für:

- Einstellungen
- Features
- Berechtigungen
- Optionen
- Dynamisches UI-Verhalten

Und plötzlich hängt daran alles. Willkommen im Club menschlicher Selbstüberschätzung.

---

```powershell
# CheckBox erstellen
$checkBox = New-Object System.Windows.Forms.CheckBox
$checkBoxNew = [System.Windows.Forms.CheckBox]::new()

# Text
$checkBox.Text = "Dark Mode aktivieren"

# Position & Größe
$checkBox.Location = New-Object System.Drawing.Point(10,10)
$checkBox.AutoSize = $true

# Standardmäßig aktiv
$checkBox.Checked = $true

```

---

## 📥 Werte auslesen

```powershell
# Aktiviert?
$state = $checkBox.Checked

# Exakter Zustand
$checkState = $checkBox.CheckState

```

---

- ***Event* – Hinweistext**  
    Auslöser / Trigger dieses Events

---

- **CheckedChanged**  
    Wird ausgelöst, sobald sich `Checked` ändert
- **CheckStateChanged**  
    Feuert bei Änderung von `CheckState`

---

- **Click**  
    Wird bei jedem Klick ausgelöst
- **DoubleClick**  
    Feuert beim Doppelklick
- **MouseDown**  
    Feuert vor `Click`
- **MouseUp**  
    Feuert nach `Click`

---

- **KeyDown**  
    Taste wird gedrückt
- **KeyUp**  
    Taste wird losgelassen

---

# Events - *CheckBox*

## ✅ CheckedChanged

Das wichtigste Event der ganzen CheckBox.

Wird ausgelöst, sobald sich der Zustand ändert.

```powershell
$checkBox.Add_CheckedChanged({
    Write-Host "CheckBox Zustand:" $checkBox.Checked
})

```

👉 Das ist normalerweise das Event, das du wirklich willst.

Nicht `Click`.

Nicht `MouseDown`.

Nicht irgendwelche kreativen Konstruktionen aus emotionalem Kontrollverlust.

---

## 🔁 CheckStateChanged

Ähnlich wie `CheckedChanged`, aber für `CheckState`.

Relevant bei `ThreeState`.

```powershell
$checkBox.ThreeState = $true

$checkBox.Add_CheckStateChanged({
    Write-Host "State:" $checkBox.CheckState
})

```

👉 Ohne `ThreeState` bringt dir das meistens exakt gar nichts.

---

## 🖱️ Click

Feuert bei jedem Klick auf die CheckBox.

```powershell
$checkBox.Add_Click({
    Write-Host "CheckBox wurde geklickt"
})

```

Das Problem:

`Click` bedeutet nicht automatisch, dass sich der Zustand geändert hat.

Das vergessen Leute ständig und bauen dadurch doppelte Logik.

---

## ⌨️ KeyDown

Für Tastatursteuerung.

```powershell
$checkBox.Add_KeyDown({
    Write-Host $_.KeyCode
})

```

👉 Viele vergessen komplett, dass Benutzer auch Tastaturen besitzen. Faszinierende gesellschaftliche Entwicklung eigentlich.

---

---

# 🧩 ThreeState

Normalerweise kennt eine CheckBox nur:

```powershell
Checked
Unchecked

```

Mit `ThreeState` kommt hinzu:

```powershell
Indeterminate

```

Beispiel:

```powershell
$checkBox.ThreeState = $true
$checkBox.CheckState = "Indeterminate"

```

Das nutzt man oft für:

- Teilweise ausgewählt
- Gemischte Zustände
- „Nicht eindeutig“

Klassisches Beispiel:

> Ordner-Auswahl mit Unterelementen  
> Einige aktiviert → graues Kästchen

---

# 🎨 Appearance = Button

Das hier kennen überraschend viele nicht:

```powershell
$checkBox.Appearance = "Button"

```

Dann wird aus der CheckBox ein Toggle-Button.

```powershell
$checkBox.Text = "Musik aktivieren"
$checkBox.Appearance = "Button"

```

👉 Sehr praktisch für moderne UI-Schalter.

Und ja, technisch bleibt es trotzdem einfach nur eine CheckBox im Kostüm. Menschen machen das übrigens auch ständig.

---

# ⚠️ Typische Stolperfallen

- `CheckedChanged` feuert auch bei Änderungen per Code

```powershell
$checkBox.Checked = $true

```

→ Event wird trotzdem ausgelöst

---

- `Click` und `CheckedChanged` gleichzeitig nutzen  
    → doppelte Ausführung

---

- `ThreeState` aktiviert, aber nur `Checked` geprüft

```powershell
if ($checkBox.Checked)

```

→ ignoriert `Indeterminate`

---

- `AutoCheck = $false`

Dann ändert die CheckBox ihren Zustand **nicht selbst**.

```powershell
$checkBox.AutoCheck = $false

```

👉 Ab da bist *du* verantwortlich.

Glückwunsch. Du bist offiziell der Zustand-Manager deines kleinen Universums.

---

# 🧩 Best Practice

- Für einfache Optionen → `CheckBox`
- Für Ein/Aus-Schalter → `Appearance = Button`
- Für mehrere zusammenhängende Optionen → `GroupBox`
- Für „eine von vielen“ → eher `RadioButton`

---

Ich greif einen Punkt raus, den viele komplett unterschätzen:

**Eine CheckBox ist kein Datenspeicher. Sie ist nur UI.**

Das hier:

```powershell
if ($checkBox.Checked)

```

…ist kein „Systemzustand“.

Das ist nur die aktuelle Anzeige im Interface.

Wenn deine komplette Logik davon abhängt, ob irgendein Kästchen gerade angehakt ist, endet dein Projekt irgendwann wie ein Keller voller Verlängerungskabel. Funktioniert irgendwie. Bis jemand dagegen tritt.

# ListBox

Die **ListBox** ist eines dieser Controls, die simpel wirken, aber erstaunlich schnell chaotisch werden, wenn man sie nicht im Griff hat. Im Kern zeigt sie eine Liste von Einträgen an, aus denen der Benutzer auswählen kann.

![Image](https://media.nngroup.com/media/editor/2020/03/05/2-multiselect-dual-listbox-final) ![Image](https://think360studio-media.s3.ap-south-1.amazonaws.com/photo/plugin/article/2022/List-Box-17102022.jpg)

---

## **Grundlagen**

#### ListBox erstellen

```powershell
# Klassisch
$listBox = New-Object System.Windows.Forms.ListBox

# .NET-Style
$listBox = [System.Windows.Forms.ListBox]::new()
```

---

#### Item hinzufügen

```powershell
$listBox.Items.Add("Apfel")
$listBox.Items.Add("Banane")
$listBox.Items.Add("Kirsche")
```

#### Mehrere Items hinzufügen

```powershell
$listBox.Items.AddRange(@("Orange","Mango","Traube"))
```

Die Methode `AddRange` nimmt nur ein Objekt, dass eine List ist entgegen, deshalb die Schreibweise `@("Orange", "Mango", "Traube")`, welches die Items als ein Array darstellt

---

#### Werte auslesen

```powershell
# Einzelne Auswahl
$selected = $listBox.SelectedItem

# Index
$index = $listBox.SelectedIndex

# Mehrere auswählen
$selectedItems = $listBox.SelectedItems

```

---

## **Eigenschaften**

<details id="bkmrk-properties-hidden-ta"><summary>Eigenschaften</summary>

<div>- ***Property** – Standardwert*  
    Beschreibung oder Erläuterung der Eigenschaft

---

</div><div>- **AllowDrop** – *$false*  
    Erlaubt Drag &amp; Drop auf die ListBox
- **Anchor** – *(Top, Left)*  
    Bestimmt, wie sich die ListBox bei Größenänderung des Containers verhält
- **BackColor** – *SystemColors.Window*  
    Hintergrundfarbe der ListBox
- **BorderStyle** – *Fixed3D*  
    Rahmenstil (`None`, `FixedSingle`, `Fixed3D`)
- **Dock** – *None*  
    Layout innerhalb des Parent-Containers (z.B. `Fill`)
- **DrawMode** – Normal  
    Zeichenmodus (`Normal`, `OwnerDrawFixed`, `OwnerDrawVariable`)
- **Enabled** – $true  
    Aktiviert oder deaktiviert die ListBox
- **Font** – *Standard-Systemfont*  
    Schriftart der Einträge
- **ForeColor** – *SystemColors.WindowText*  
    Textfarbe der Einträge
- **FormattingEnabled** – *$true*  
    Aktiviert Formatierung für komplexe Objekte
- **HorizontalScrollbar** – *$false*  
    Zeigt horizontale Scrollbar an
- **Location** – *(0,0)*  
    Position innerhalb des Containers
- **Name** – *""*  
    Interner Name der ListBox
- **ScrollAlwaysVisible** – *$false*  
    Scrollbar immer anzeigen, auch wenn nicht nötig
- **TabIndex** – 0  
    Reihenfolge beim Durchtabben
- **TabStop** – *$true*  
    Ob die ListBox per Tab erreichbar ist
- **TopIndex** – 0  
    Index des obersten sichtbaren Elements
- **Visible** – *$true*  
    Sichtbarkeit der ListBox

</div>##### **Items**

- **Items** – *(leer)*  
    Sammlung aller Listeneinträge
- **MultiColumn** – *$false*  
    Mehrspaltige Darstellung aktivieren
- **SelectedIndex** – *-1*  
    Index des aktuell ausgewählten Elements (`-1` = nichts)
- **SelectedItem** – *$null*  
    Aktuell ausgewähltes Element
- **SelectedItems** – *(leer)*  
    Collection aller ausgewählten Elemente (bei `Multi-Select`)
- **SelectionMode** – *One*  
    Auswahlmodus   
    
    - `One` → Nur ein Eintrag
    - `MultiSimple` → Mehrere ohne STRG
    - `MultiExtended` → Mehrere mit STRG/SHIFT
- **Sorted** – *$false*  
    Sortiert Einträge automatisch alphabetisch

##### **Größe**

- **ColumnWidth** – 0  
    Breite der Spalten bei MultiColumn (`0` = automatisch)
- **Height** – *(abhängig vom Layout)*  
    Höhe der ListBox
- **HorizontalExtent** – 0  
    Virtuelle Breite für horizontales Scrollen
- **IntegralHeight** – *$true*  
    Passt Höhe automatisch an volle Einträge an (kein halbes Item unten)
- **ItemHeight** – *(abhängig von Font)*  
    Höhe eines einzelnen Eintrags
- **Size** – *(Width=120, Height=96)*  
    Größe der ListBox
- **Width** – *(abhängig vom Layout)*  
    Breite der ListBox

</details>---

## **Events**

<details id="bkmrk-events-event-%E2%80%93-hinwe"><summary>Events</summary>

<div>- ***Event** – Hinweistext*  
    Auslöser / Trigger dieses Events

---

</div><div>- **SelectedIndexChanged**  
    Wird ausgelöst, sobald sich die Auswahl ändert.
- **SelectedValueChanged**  
    Fast wie `SelectedIndexChanged`, aber subtil anders.  
    Feuert, wenn sich der **Value** ändert (relevant bei `ValueMember`)
- ---
    
    **Click**  
    Löst bei jedem Klick auf das Control aus
- **DoubleClick** Feuert, beim Doppelklick auf das Control / oder ein Item
- **MouseDown** Feuert **vor** dem Click
- **MouseUp** Feuert **nach** dem Click
- ---
    
    **KeyDown** Wird ausgelöst, wenn eine Taste gedrückt wird
- **KeyUp** Sowie `KeyDown`, aber erst wenn losgelassen wird

</div></details>#### **SelectedIndexChanged**

Wird ausgelöst, sobald sich die Auswahl ändert.

```powershell
$listBox.Add_SelectedIndexChanged({
    Write-Host "Ausgewählt:" $listBox.SelectedItem
})

```

---

#### **SelectedValueChanged**

Fast wie `SelectedIndexChanged`… aber subtil anders.  
Feuert, wenn sich der **Value** ändert (relevant bei `ValueMember`).

```powershell
$listBox.Add_SelectedValueChanged({
    Write-Host "Value geändert:" $listBox.SelectedItem
})

```

👉 Unterschied merkst du erst, wenn du mit Objekten arbeitest.

---

#### **Click**

Wird bei jedem Klick ausgelöst.  
Ja, auch wenn sich **nichts ändert**. Klassiker für doppelte Logik.

```powershell
$listBox.Add_Click({
    Write-Host "ListBox wurde geklickt"
})

```

---

#### **DoubleClick**

Wenn der User doppelt klickt. Perfekt für „öffnen“, „starten“, etc.

```powershell
$listBox.Add_DoubleClick({
    Write-Host "Doppelklick auf:" $listBox.SelectedItem
})

```

👉 UX-technisch oft sinnvoller als Button daneben.

---

#### **KeyDown**

Für Tastatursteuerung. Wird ausgelöst, wenn eine Taste gedrückt wird.

```powershell
$listBox.Add_KeyDown({
    if ($_.KeyCode -eq "Enter") {
        Write-Host "Enter auf:" $listBox.SelectedItem
    }
})

```

👉 Das ist der Moment, wo dein UI sich plötzlich „professionell“ anfühlt.

---

#### **KeyUp**

Wie KeyDown, nur nachdem losgelassen wurde.

```powershell
$listBox.Add_KeyUp({
    Write-Host "Taste losgelassen:" $_.KeyCode
})

```

---

#### **MouseDown**

Feuert **vor** Click. Gut für spezielle Logik.

```powershell
$listBox.Add_MouseDown({
    Write-Host "MouseDown erkannt"
})

```

---

#### **MouseUp**

Nach dem Klick.

```powershell
$listBox.Add_MouseUp({
    Write-Host "MouseUp erkannt"
})

```

---

## **Tipps &amp; Tricks** *- TabControl*

Ich sag’s dir direkt, weil ich genau weiß, wie das läuft:

Du kombinierst sowas:

```powershell
Click
SelectedIndexChanged
DoubleClick

```

…und wunderst dich, warum dein Code **mehrfach läuft**.

👉 Beispiel:

- Klick → `MouseDown`
- Klick → `Click`
- Auswahl ändert sich → `SelectedIndexChanged`

→ Boom, drei Events für einen simplen Klick.

---

##### 🧩 Mini-Leitfaden (der dir später Nerven spart)

- Auswahl reagieren → `SelectedIndexChanged`
- Aktion starten → `DoubleClick` oder `Enter`
- Nur Klick erkennen → `Click`
- Präzise Kontrolle → `MouseDown`

---

## ➕ Items verwalten

```powershell
# Entfernen
$listBox.Items.Remove("Apfel")

# Alles löschen
$listBox.Items.Clear()

# Einfügen an Position
$listBox.Items.Insert(0, "Neu")

```

---

## 🎨 Nützliche Tricks

### Automatisch sortieren

```powershell
$listBox.Sorted = $true

```

### Mehrspaltig anzeigen

```powershell
$listBox.MultiColumn = $true

```

### Scrollbar erzwingen

```powershell
$listBox.HorizontalScrollbar = $true

```

---

## ⚠️ Typische Stolperfallen

- `SelectedItem` ist `$null`, wenn nichts gewählt ist → obvious, aber wird ständig vergessen
- `SelectedItems` ist **kein Array**, sondern Collection → verhält sich leicht anders
- Bei `MultiExtended`: Benutzer müssen STRG drücken → sonst denkt jeder, dein UI ist kaputt
- `Items.AddRange()` erwartet ein Array → kein wild zusammengebauter String-Müll

---

## 🧩 Best Practice

- Für einfache Auswahl → `ListBox`
- Für strukturierte Daten → **ListView** (sonst wird’s hässlich)
- Für kleine Auswahl → lieber **ComboBox**

---

Ich greif einen Punkt raus, den du wahrscheinlich unterschätzt:

**Was speicherst du eigentlich in der ListBox? Strings oder Objekte?**

Wenn du nur Strings reinwirfst, verbaust du dir später jede sinnvolle Logik.  
Pack lieber direkt Objekte rein:

```powershell
$listBox.Items.Add([PSCustomObject]@{
    Name = "Chrome"
    Version = "123"
})

```

Und dann:

```powershell
$listBox.DisplayMember = "Name"

```

Das ist der Unterschied zwischen „funktioniert irgendwie“ und „ich hab Kontrolle über meinen Code“.

Das ist so ein klassischer Punkt, wo Leute sich später selbst hassen, weil sie am Anfang “einfach schnell Strings genommen haben”.

# ListView

Ein `ListView` ist ein Steuerelement zur Darstellung einer Sammlung von Elementen. Je nach Einstellung können die Elemente als große oder kleine Symbole, als einfache Liste oder als Tabelle mit mehreren Spalten dargestellt werden.

Im Gegensatz zu einer `ListBox` kann ein `ListView` zusätzliche Informationen zu jedem Eintrag darstellen und eignet sich dadurch besonders für Datei- und Datenübersichten.

---

## **Grundlagen**

Ein `ListView` besteht im Wesentlichen aus drei Komponenten:

- `ListView` → stellt die Liste dar
- `ListViewItem` → repräsentiert einen einzelnen Eintrag
- `ListViewSubItem` → enthält zusätzliche Spaltenwerte eines Eintrags

Beispielsweise kann eine Dateiliste so aufgebaut werden:

<table id="bkmrk-name-typ-gr%C3%B6%C3%9Fe-dokum"><thead><tr><th>Name</th><th>Typ</th><th>Größe</th></tr></thead><tbody><tr><td>`Dokument.txt`</td><td>Textdatei</td><td>12 KB</td></tr><tr><td>`Bild.png`</td><td>Bild</td><td>1,4 MB</td></tr><tr><td>`Programm.exe`</td><td>Anwendung</td><td>8 MB</td></tr></tbody></table>

Dabei entspricht jede Zeile einem `ListViewItem` und jede zusätzliche Spalte einem `ListViewSubItem`.

---

#### ListView erstellen

```powershell
# Klassisch
$listView = New-Object System.Windows.Forms.ListView

# .NET-Style
$listView = [System.Windows.Forms.ListView]::new()
```

---

#### ListView hinzufügen

Ein `ListView` wird wie jedes andere Control der `Controls`-Collection seines Parent-Containers hinzugefügt.

```powershell
$form.Controls.Add($listView)

# oder

$tabPage.Controls.Add($listView)
```

---

#### Einfache Einträge hinzufügen

Ein einzelner Eintrag kann direkt über die `Items`-Collection hinzugefügt werden.

```powershell
$listView.Items.Add("Dokument.txt")
$listView.Items.Add("Bild.png")
$listView.Items.Add("Programm.exe")

```

---

## **Eigenschaften**

<table id="bkmrk-eigenschaft-beschrei"><thead><tr><th>Eigenschaft</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`Activation`</td><td>Bestimmt, wie Listenelemente durch den Mauszeiger aktiviert werden.</td></tr><tr><td>`Alignment`</td><td>Bestimmt die Anordnung der Elemente bei Symbolansichten.</td></tr><tr><td>`AutoArrange`</td><td>Ordnet Elemente bei Symbolansichten automatisch an.</td></tr><tr><td>`BackColor`</td><td>Legt die Hintergrundfarbe fest.</td></tr><tr><td>`CheckBoxes`</td><td>Zeigt neben jedem Eintrag eine Checkbox an.</td></tr><tr><td>`Columns`</td><td>Enthält die Spalten des `ListView`.</td></tr><tr><td>`Dock`</td><td>Dockt das `ListView` am Parent-Container an.</td></tr><tr><td>`Enabled`</td><td>Legt fest, ob das `ListView` verwendet werden kann.</td></tr><tr><td>`Font`</td><td>Legt Schriftart, -größe und -stil fest.</td></tr><tr><td>`ForeColor`</td><td>Legt die Textfarbe fest.</td></tr><tr><td>`FullRowSelect`</td><td>Markiert bei `Details` die gesamte Zeile eines ausgewählten Eintrags.</td></tr><tr><td>`GridLines`</td><td>Zeigt bei `Details` Gitternetzlinien zwischen Zeilen und Spalten an.</td></tr><tr><td>`Groups`</td><td>Enthält die Gruppen des `ListView`.</td></tr><tr><td>`HeaderStyle`</td><td>Bestimmt die Darstellung der Spaltenüberschriften.</td></tr><tr><td>`HideSelection`</td><td>Legt fest, ob eine Auswahl beim Verlust des Fokus sichtbar bleibt.</td></tr><tr><td>`HoverSelection`</td><td>Wählt ein Element automatisch aus, wenn der Mauszeiger darüber bewegt wird.</td></tr><tr><td>`Items`</td><td>Enthält alle `ListViewItem` des `ListView`.</td></tr><tr><td>`LabelEdit`</td><td>Erlaubt das direkte Bearbeiten der Beschriftung eines Eintrags.</td></tr><tr><td>`LabelWrap`</td><td>Legt fest, ob Beschriftungen in Symbolansichten umgebrochen werden.</td></tr><tr><td>`LargeImageList`</td><td>Enthält die Bilder für die große Symbolansicht.</td></tr><tr><td>`Location`</td><td>Bestimmt die Position im Parent-Container.</td></tr><tr><td>`Margin`</td><td>Legt den äußeren Abstand fest.</td></tr><tr><td>`MultiSelect`</td><td>Legt fest, ob mehrere Einträge gleichzeitig ausgewählt werden können.</td></tr><tr><td>`OwnerDraw`</td><td>Legt fest, ob die Darstellung der ListView-Elemente vollständig oder teilweise selbst gezeichnet werden soll.</td></tr><tr><td>`Scrollable`</td><td>Aktiviert bzw. deaktiviert Scrollleisten.</td></tr><tr><td>`SelectedItems`</td><td>Enthält die aktuell ausgewählten Einträge.</td></tr><tr><td>`ShowGroups`</td><td>Legt fest, ob Gruppen angezeigt werden.</td></tr><tr><td>`ShowItemToolTips`</td><td>Aktiviert Tooltips für einzelne Einträge.</td></tr><tr><td>`Size`</td><td>Bestimmt Breite und Höhe.</td></tr><tr><td>`SmallImageList`</td><td>Enthält die Bilder für kleine Symbole.</td></tr><tr><td>`Sorting`</td><td>Bestimmt die automatische Sortierung der Einträge.</td></tr><tr><td>`StateImageList`</td><td>Enthält Statusbilder, beispielsweise für Checkbox-Zustände.</td></tr><tr><td>`TileSize`</td><td>Bestimmt die Größe von Elementen in der `Tile`-Ansicht.</td></tr><tr><td>`View`</td><td>Bestimmt die Darstellungsart des `ListView`.</td></tr><tr><td>`Visible`</td><td>Legt fest, ob das `ListView` sichtbar ist.</td></tr></tbody></table>

---

<details id="bkmrk-checkboxes-checkboxe"><summary>CheckBoxes</summary>

### CheckBoxes

**Typ** = `[System.Boolean]`

Der Wert von `CheckBoxes` legt fest, ob neben jedem Eintrag eine Checkbox angezeigt wird.

```powershell
$listView.CheckBoxes = $true

```

Der Zustand einer Checkbox wird über die Eigenschaft `Checked` des jeweiligen `ListViewItem` gesteuert.

```powershell
$listView.Items[0].Checked = $true

```

> 💡 **Hinweis** Die Checkbox gehört zum jeweiligen `ListViewItem` und wird nicht über eine separate Collection verwaltet.

</details><details id="bkmrk-columns-columns-typ-"><summary>Columns</summary>

### Columns

**Typ** = `[System.Windows.Forms.ListView.ColumnHeaderCollection]`

Die Eigenschaft `Columns` enthält die Spalten des `ListView`.

Spalten werden hauptsächlich in der `Details`-Ansicht verwendet.

```powershell
$listView.View = "Details"

$listView.Columns.Add("Name", 200)
$listView.Columns.Add("Typ", 100)
$listView.Columns.Add("Größe", 100)

```

Die zweite Angabe bestimmt dabei die Breite der Spalte in Pixeln.

> 💡 **Hinweis** Die Spaltenüberschriften werden nur sichtbar, wenn `View` auf `Details` gesetzt ist.

</details><details id="bkmrk-fullrowselect-fullro"><summary>FullRowSelect</summary>

### FullRowSelect

**Typ** = `[System.Boolean]`

Der Wert von `FullRowSelect` legt fest, ob bei einer Auswahl in der `Details`-Ansicht die gesamte Zeile markiert wird.

Standardmäßig ist diese Eigenschaft deaktiviert.

```powershell
$listView.FullRowSelect = $true

```

Ohne `FullRowSelect` wird bei der Auswahl hauptsächlich das erste Feld des Eintrags hervorgehoben.

> 💡 **Hinweis** Die Eigenschaft ist insbesondere bei tabellarischen Darstellungen sinnvoll, da dadurch deutlich erkennbar ist, welche komplette Zeile ausgewählt wurde.

</details><details id="bkmrk-gridlines-gridlines-"><summary>GridLines</summary>

### GridLines

**Typ** = `[System.Boolean]`

Der Wert von `GridLines` legt fest, ob zwischen den Zeilen und Spalten Gitternetzlinien angezeigt werden.

```powershell
$listView.GridLines = $true

```

Die Gitternetzlinien werden nur in der `Details`-Ansicht angezeigt.

</details><details id="bkmrk-groups-groups-typ-%3D-"><summary>Groups</summary>

### Groups

**Typ** = `[System.Windows.Forms.ListViewGroupCollection]`

Die Eigenschaft `Groups` enthält die Gruppen des `ListView`.

Eine Gruppe kann beispielsweise so erstellt werden:

```powershell
$group = [System.Windows.Forms.ListViewGroup]::new("Dokumente")

$listView.Groups.Add($group)

```

Ein `ListViewItem` kann anschließend einer Gruppe zugewiesen werden:

```powershell
$item = [System.Windows.Forms.ListViewItem]::new("Dokument.txt")
$item.Group = $group

$listView.Items.Add($item)

```

</details><details id="bkmrk-items-items-typ-%3D-%5Bs"><summary>Items</summary>

### Items

**Typ** = `[System.Windows.Forms.ListViewItemCollection]`

Die Eigenschaft `Items` enthält alle Einträge des `ListView`.

Über die Collection können neue Einträge hinzugefügt, vorhandene Einträge entfernt oder einzelne Einträge abgerufen werden.

```powershell
$listView.Items.Add("Dokument.txt")

```

Ein `ListViewItem` kann auch explizit erstellt werden:

```powershell
$item = [System.Windows.Forms.ListViewItem]::new("Dokument.txt")

$listView.Items.Add($item)

```

Die Collection enthält ausschließlich die Haupteinträge. Zusätzliche Spalten werden über die `SubItems` des jeweiligen `ListViewItem` verwaltet.

</details><details id="bkmrk-labeledit-labeledit-"><summary>LabelEdit</summary>

### LabelEdit

**Typ** = `[System.Boolean]`

Der Wert von `LabelEdit` legt fest, ob der Benutzer die Beschriftung eines `ListViewItem` direkt im `ListView` bearbeiten kann.

```powershell
$listView.LabelEdit = $true

```

Wird die Bearbeitung aktiviert, kann der Benutzer beispielsweise durch langsames Doppelklicken auf einen Eintrag dessen Text ändern.

Die Ereignisse `BeforeLabelEdit` und `AfterLabelEdit` ermöglichen es, die Bearbeitung zu kontrollieren.

</details><details id="bkmrk-largeimagelist-large"><summary>LargeImageList</summary>

### LargeImageList

**Typ** = `[System.Windows.Forms.ImageList]`

`LargeImageList` legt die `ImageList` für große Symbole fest.

Sie wird insbesondere bei der Darstellungsart `LargeIcon` verwendet.

```powershell
$listView.LargeImageList = $imageList
$listView.View = "LargeIcon"

```

</details><details id="bkmrk-multiselect-multisel"><summary>MultiSelect</summary>

### MultiSelect

**Typ** = `[System.Boolean]`

Der Wert von `MultiSelect` legt fest, ob mehrere Einträge gleichzeitig ausgewählt werden können.

Standardmäßig ist `MultiSelect` auf `True` gesetzt.

```powershell
$listView.MultiSelect = $false

```

Ist `MultiSelect` deaktiviert, kann immer nur ein `ListViewItem` ausgewählt werden.

</details><details id="bkmrk-ownerdraw-ownerdraw-"><summary>OwnerDraw</summary>

### OwnerDraw

**Typ** = `[System.Boolean]`

Der Wert von `OwnerDraw` legt fest, ob die Darstellung des `ListView` vom Entwickler selbst gezeichnet werden soll.

Standardmäßig besitzt diese Eigenschaft den Wert `False`, wodurch das `ListView` seine Elemente automatisch anhand der festgelegten Eigenschaften darstellt.

Wird `OwnerDraw` auf `True` gesetzt, können die einzelnen Bereiche des `ListView` über die entsprechenden Zeichen-Events individuell gezeichnet werden. Dazu gehören unter anderem `DrawColumnHeader`, `DrawItem` und `DrawSubItem`.

```powershell
$listView.OwnerDraw = $true
```

> 💡 **Hinweis**  
> Bei aktiviertem `OwnerDraw` müssen die entsprechenden `Draw...`-Events behandelt werden, wenn die Darstellung individuell angepasst werden soll. Andernfalls bleibt die Darstellung je nach verwendetem View und behandelten Events unvollständig.

</details><details id="bkmrk-selecteditems-select"><summary>SelectedItems</summary>

### SelectedItems

**Typ** = `[System.Windows.Forms.ListView.SelectedListViewItemCollection]`

Die Eigenschaft `SelectedItems` enthält alle aktuell ausgewählten `ListViewItem`.

```powershell
$listView.SelectedItems

```

Der erste ausgewählte Eintrag kann beispielsweise so abgerufen werden:

```powershell
$item = $listView.SelectedItems[0]

Write-Host $item.Text

```

Bei aktiviertem `MultiSelect` kann die Collection mehrere Einträge enthalten.

> ⚠️ **Hinweis** Vor dem Zugriff auf `[0]` sollte geprüft werden, ob überhaupt ein Eintrag ausgewählt wurde.

```powershell
if ($listView.SelectedItems.Count -gt 0) {
    $item = $listView.SelectedItems[0]
}

```

</details><details id="bkmrk-showgroups-showgroup"><summary>ShowGroups</summary>

### ShowGroups

**Typ** = `[System.Boolean]`

Der Wert von `ShowGroups` legt fest, ob die im `Groups`-Container definierten Gruppen angezeigt werden.

```powershell
$listView.ShowGroups = $true

```

Gruppen werden hauptsächlich verwendet, um größere Mengen von Einträgen logisch zu unterteilen.

</details><details id="bkmrk-smallimagelist-small"><summary>SmallImageList</summary>

### SmallImageList

**Typ** = `[System.Windows.Forms.ImageList]`

`SmallImageList` legt die `ImageList` fest, aus der das `ListView` kleine Symbole für seine Einträge bezieht.

```powershell
$listView.SmallImageList = $imageList

```

Welches Bild für einen bestimmten Eintrag verwendet wird, wird über `ImageIndex` oder `ImageKey` des `ListViewItem` festgelegt.

```powershell
$item.ImageKey = "document"

```

</details><details id="bkmrk-sorting-sorting-typ-"><summary>Sorting</summary>

### Sorting

**Typ** = `[System.Windows.Forms.SortOrder]`

Der Wert von `Sorting` bestimmt, ob und wie die Einträge automatisch sortiert werden.

Folgende Werte stehen zur Verfügung:

<table><thead><tr><th>Wert</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`None`</td><td>Keine automatische Sortierung</td></tr><tr><td>`Ascending`</td><td>Aufsteigende Sortierung</td></tr><tr><td>`Descending`</td><td>Absteigende Sortierung</td></tr></tbody></table>

```powershell
$listView.Sorting = "Ascending"

```

> 💡 **Hinweis** Die automatische Sortierung orientiert sich standardmäßig am Text des `ListViewItem`.

</details><details id="bkmrk-stateimagelist-state"><summary>StateImageList</summary>

### StateImageList

**Typ** = `[System.Windows.Forms.ImageList]`

`StateImageList` enthält Bilder, die den Status eines `ListViewItem` darstellen.

Sie kann beispielsweise verwendet werden, um unterschiedliche Zustände eines Eintrags visuell darzustellen.

```powershell
$listView.StateImageList = $stateImageList

```

Der verwendete Zustand wird über `StateImageIndex` des jeweiligen `ListViewItem` festgelegt.

</details><details id="bkmrk-view-view-typ-%3D-%5Bsys"><summary>View</summary>

### View

**Typ** = `[System.Windows.Forms.View]`

Der Wert von `View` bestimmt, wie die Elemente des `ListView` dargestellt werden.

Folgende Darstellungsarten stehen zur Verfügung:

<table><thead><tr><th>Wert</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`Details`</td><td>Tabellarische Darstellung mit Spalten</td></tr><tr><td>`LargeIcon`</td><td>Große Symbole mit Beschriftung</td></tr><tr><td>`SmallIcon`</td><td>Kleine Symbole mit Beschriftung</td></tr><tr><td>`List`</td><td>Einfache Liste mit kleinen Symbolen</td></tr><tr><td>`Tile`</td><td>Kachelansicht</td></tr></tbody></table>

Für eine tabellarische Darstellung muss `View` auf `Details` gesetzt werden.

```powershell
$listView.View = "Details"

```

Beispiel für eine einfache Dateiliste:

```powershell
$listView.View = "Details"

$listView.Columns.Add("Name", 200)
$listView.Columns.Add("Typ", 100)
$listView.Columns.Add("Größe", 100)

```

> 💡 **Hinweis** Eigenschaften wie `Columns`, `GridLines` und `FullRowSelect` sind insbesondere für die `Details`-Ansicht relevant.

</details>---

# ListViewItem

Ein `ListViewItem` repräsentiert einen einzelnen Eintrag innerhalb eines `ListView`.

Ein Eintrag besitzt mindestens einen sichtbaren Haupttext. Zusätzlich können weitere Werte über `SubItems` hinzugefügt werden.

### Eintrag mit mehreren Spalten

```powershell
$item = [System.Windows.Forms.ListViewItem]::new("Dokument.txt")

$item.SubItems.Add("Textdatei")
$item.SubItems.Add("12 KB")

$listView.Items.Add($item)

```

Bei folgendem `ListView`:

```powershell
$listView.View = "Details"

$listView.Columns.Add("Name", 200)
$listView.Columns.Add("Typ", 100)
$listView.Columns.Add("Größe", 100)

```

entsteht daraus:

<table id="bkmrk-name-typ-gr%C3%B6%C3%9Fe-dokum-1"><thead><tr><th>Name</th><th>Typ</th><th>Größe</th></tr></thead><tbody><tr><td>Dokument.txt</td><td>Textdatei</td><td>12 KB</td></tr></tbody></table>

Dabei gilt:

```text
ListViewItem
├── Text
├── SubItems[1]
├── SubItems[2]
└── ...

```

Das erste `SubItem` entspricht dabei dem Haupttext des `ListViewItem`.

---

## **Methoden**

## Übersicht

<table id="bkmrk-methode-beschreibung"><thead><tr><th>Methode</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`ArrangeIcons()`</td><td>Ordnet Symbole im `ListView` an.</td></tr><tr><td>`BeginUpdate()`</td><td>Verhindert während einer Änderung die Aktualisierung der Darstellung.</td></tr><tr><td>`Clear()`</td><td>Entfernt alle Einträge und Spalten.</td></tr><tr><td>`EndUpdate()`</td><td>Aktiviert nach `BeginUpdate()` wieder die Aktualisierung.</td></tr><tr><td>`EnsureVisible()`</td><td>Stellt sicher, dass ein bestimmter Eintrag sichtbar ist.</td></tr><tr><td>`FindItemWithText()`</td><td>Sucht nach einem Eintrag anhand seines Textes.</td></tr><tr><td>`GetItemAt()`</td><td>Ermittelt den Eintrag an einer bestimmten Position.</td></tr><tr><td>`HitTest()`</td><td>Ermittelt, welches Element sich an einer Mausposition befindet.</td></tr><tr><td>`Sort()`</td><td>Sortiert die Einträge.</td></tr></tbody></table>

---

<details id="bkmrk-beginupdate%28%29-beginu"><summary>BeginUpdate()</summary>

### BeginUpdate()

Die Methode `BeginUpdate()` verhindert, dass das `ListView` während umfangreicher Änderungen nach jeder einzelnen Änderung neu gezeichnet wird.

```powershell
$listView.BeginUpdate()

foreach ($file in $files) {
    $listView.Items.Add($file.Name)
}

$listView.EndUpdate()

```

Dies ist besonders bei vielen Einträgen sinnvoll.

> 💡 **Hinweis** `BeginUpdate()` sollte immer zusammen mit `EndUpdate()` verwendet werden. Andernfalls kann die Aktualisierung des Controls ausbleiben. Menschliche Softwareentwicklung hat also auch hier einen „vergessen, wieder einzuschalten“-Modus.

</details><details id="bkmrk-endupdate%28%29-endupdat"><summary>EndUpdate()</summary>

### EndUpdate()

Die Methode `EndUpdate()` beendet die mit `BeginUpdate()` begonnene Aktualisierungssperre.

```powershell
$listView.BeginUpdate()

$listView.Items.Clear()
$listView.Items.Add("Eintrag 1")
$listView.Items.Add("Eintrag 2")

$listView.EndUpdate()

```

Nach `EndUpdate()` wird das `ListView` wieder aktualisiert.

</details><details id="bkmrk-clear%28%29-clear%28%29-die-"><summary>Clear()</summary>

### Clear()

Die Methode `Clear()` entfernt alle Einträge und Spalten aus dem `ListView`.

```powershell
$listView.Clear()

```

> ⚠️ **Hinweis** `Clear()` entfernt nicht nur die `Items`, sondern auch die `Columns`. Soll ausschließlich der Inhalt entfernt werden, sollte stattdessen `Items.Clear()` verwendet werden.

```powershell
$listView.Items.Clear()

```

</details><details id="bkmrk-ensurevisible%28%29-ensu"><summary>EnsureVisible()</summary>

### EnsureVisible()

Die Methode `EnsureVisible()` sorgt dafür, dass ein bestimmter Eintrag im sichtbaren Bereich des `ListView` liegt.

```powershell
$listView.EnsureVisible(10)

```

Der angegebene Parameter ist der Index des Eintrags.

**Syntax**

```powershell
$listView.EnsureVisible(Index)

```

</details><details id="bkmrk-finditemwithtext%28%29-f"><summary>FindItemWithText()</summary>

### FindItemWithText()

Die Methode `FindItemWithText()` sucht nach einem `ListViewItem`, dessen Text mit dem angegebenen Suchtext übereinstimmt.

```powershell
$item = $listView.FindItemWithText("Dokument.txt")

```

Wird kein passender Eintrag gefunden, wird `$null` zurückgegeben.

```powershell
if ($item) {
    Write-Host "Eintrag gefunden: $($item.Text)"
}

```

</details><details id="bkmrk-getitemat%28%29-getitema"><summary>GetItemAt()</summary>

### GetItemAt()

Die Methode `GetItemAt()` ermittelt das `ListViewItem`, das sich an einer bestimmten Position befindet.

```powershell
$item = $listView.GetItemAt(50, 30)

```

Die Koordinaten beziehen sich auf das `ListView`.

Wird an der angegebenen Position kein Eintrag gefunden, wird `$null` zurückgegeben.

</details><details id="bkmrk-sort%28%29-sort%28%29-die-me"><summary>Sort()</summary>

### Sort()

Die Methode `Sort()` führt eine Sortierung der Einträge durch.

```powershell
$listView.Sort()

```

Die Sortierreihenfolge wird durch die Eigenschaft `Sorting` bestimmt.

```powershell
$listView.Sorting = "Ascending"
$listView.Sort()

```

</details>---

## **Events**

## Übersicht

<table id="bkmrk-event-beschreibung-a"><thead><tr><th>Event</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`AfterLabelEdit`</td><td>Wird ausgelöst, nachdem die Beschriftung eines Eintrags bearbeitet wurde.</td></tr><tr><td>`BeforeLabelEdit`</td><td>Wird ausgelöst, bevor die Beschriftung eines Eintrags bearbeitet wird.</td></tr><tr><td>`ColumnClick`</td><td>Wird ausgelöst, wenn auf eine Spaltenüberschrift geklickt wird.</td></tr><tr><td>`ItemActivate`</td><td>Wird ausgelöst, wenn ein Eintrag aktiviert wird.</td></tr><tr><td>`ItemCheck`</td><td>Wird ausgelöst, bevor sich der Checkbox-Zustand eines Eintrags ändert.</td></tr><tr><td>`ItemChecked`</td><td>Wird ausgelöst, nachdem sich der Checkbox-Zustand geändert hat.</td></tr><tr><td>`ItemDrag`</td><td>Wird ausgelöst, wenn ein Eintrag mit der Maus gezogen wird.</td></tr><tr><td>`ItemSelectionChanged`</td><td>Wird ausgelöst, wenn sich der Auswahlzustand eines Eintrags ändert.</td></tr><tr><td>`SelectedIndexChanged`</td><td>Wird ausgelöst, wenn sich die Auswahl im `ListView` ändert.</td></tr></tbody></table>

---

<details id="bkmrk-itemselectionchanged"><summary>ItemSelectionChanged</summary>

### ItemSelectionChanged

Das Event `ItemSelectionChanged` wird ausgelöst, wenn sich der Auswahlzustand eines `ListViewItem` verändert.

```powershell
$listView.Add_ItemSelectionChanged({
    param($sender, $e)

    Write-Host "Auswahl geändert: $($e.Item.Text)"
})

```

Über das Event-Argument `$e` kann unter anderem auf das betroffene `Item` zugegriffen werden.

```powershell
$e.Item

```

Der neue Auswahlzustand kann über `IsSelected` ermittelt werden.

```powershell
if ($e.IsSelected) {
    Write-Host "$($e.Item.Text) wurde ausgewählt."
}

```

</details><details id="bkmrk-selectedindexchanged"><summary>SelectedIndexChanged</summary>

### SelectedIndexChanged

Das Event `SelectedIndexChanged` wird ausgelöst, wenn sich die Auswahl des `ListView` verändert.

```powershell
$listView.Add_SelectedIndexChanged({
    param($sender, $e)

    Write-Host "Auswahl geändert."
})

```

Das Event eignet sich insbesondere, wenn nach einer Änderung der Auswahl mit den aktuell ausgewählten Elementen gearbeitet werden soll.

```powershell
$listView.Add_SelectedIndexChanged({
    if ($this.SelectedItems.Count -gt 0) {
        Write-Host $this.SelectedItems[0].Text
    }
})

```

> 💡 **Hinweis** Wenn das konkrete betroffene `ListViewItem` benötigt wird, ist `ItemSelectionChanged` meist geeigneter.

</details><details id="bkmrk-itemactivate-itemact"><summary>ItemActivate</summary>

### ItemActivate

Das Event `ItemActivate` wird ausgelöst, wenn ein `ListViewItem` aktiviert wird.

Je nach `Activation`-Einstellung kann dies beispielsweise durch einen einfachen oder doppelten Mausklick erfolgen.

```powershell
$listView.Add_ItemActivate({
    param($sender, $e)

    if ($this.SelectedItems.Count -gt 0) {
        Write-Host "Aktiviert: $($this.SelectedItems[0].Text)"
    }
})

```

</details><details id="bkmrk-itemchecked-itemchec"><summary>ItemChecked</summary>

### ItemChecked

Das Event `ItemChecked` wird ausgelöst, nachdem sich der Checkbox-Zustand eines `ListViewItem` geändert hat.

```powershell
$listView.Add_ItemChecked({
    param($sender, $e)

    if ($e.Item.Checked) {
        Write-Host "$($e.Item.Text) aktiviert"
    }
    else {
        Write-Host "$($e.Item.Text) deaktiviert"
    }
})

```

Im Gegensatz zu `ItemCheck` findet die Änderung zu diesem Zeitpunkt bereits statt.

</details><details id="bkmrk-itemcheck-itemcheck-"><summary>ItemCheck</summary>

### ItemCheck

Das Event `ItemCheck` wird ausgelöst, bevor sich der Checkbox-Zustand eines `ListViewItem` ändert.

```powershell
$listView.Add_ItemCheck({
    param($sender, $e)

    Write-Host "Checkbox wird geändert."
})

```

Das Event eignet sich insbesondere, wenn die Änderung geprüft oder verhindert werden soll.

Der geplante neue Zustand steht in `NewValue`.

```powershell
$listView.Add_ItemCheck({
    param($sender, $e)

    Write-Host "Neuer Zustand: $($e.NewValue)"
})

```

</details><details id="bkmrk-columnclick-columncl"><summary>ColumnClick</summary>

### ColumnClick

Das Event `ColumnClick` wird ausgelöst, wenn der Benutzer auf eine Spaltenüberschrift klickt.

```powershell
$listView.Add_ColumnClick({
    param($sender, $e)

    Write-Host "Spalte $($e.Column) wurde angeklickt."
})

```

`Column` enthält den Index der angeklickten Spalte.

Das Event eignet sich beispielsweise, um beim Klick auf eine Spaltenüberschrift die Sortierreihenfolge zu ändern.

</details><details id="bkmrk-beforelabeledit-befo"><summary>BeforeLabelEdit</summary>

### BeforeLabelEdit

Das Event `BeforeLabelEdit` wird ausgelöst, bevor die Beschriftung eines `ListViewItem` bearbeitet wird.

```powershell
$listView.Add_BeforeLabelEdit({
    param($sender, $e)

    Write-Host "Bearbeitung wird gestartet."
})

```

Die Bearbeitung kann über `CancelEdit` verhindert werden.

```powershell
$listView.Add_BeforeLabelEdit({
    param($sender, $e)

    $e.CancelEdit = $true
})

```

</details><details id="bkmrk-afterlabeledit-after"><summary>AfterLabelEdit</summary>

### AfterLabelEdit

Das Event `AfterLabelEdit` wird ausgelöst, nachdem die Beschriftung eines `ListViewItem` bearbeitet wurde.

```powershell
$listView.Add_AfterLabelEdit({
    param($sender, $e)

    Write-Host "Neuer Text: $($e.Label)"
})

```

Über `Label` kann der neu eingegebene Text abgerufen werden.

</details>---

# Beispiel

Das folgende Beispiel erstellt ein einfaches `ListView` zur Darstellung einer Dateiliste.

```powershell
$listView = [System.Windows.Forms.ListView]::new()

$listView.View = "Details"
$listView.FullRowSelect = $true
$listView.GridLines = $true
$listView.MultiSelect = $false
$listView.Dock = "Fill"

$listView.Columns.Add("Name", 250)
$listView.Columns.Add("Typ", 120)
$listView.Columns.Add("Größe", 100)

$item = [System.Windows.Forms.ListViewItem]::new("Dokument.txt")
$item.SubItems.Add("Textdatei")
$item.SubItems.Add("12 KB")

$listView.Items.Add($item)

$form.Controls.Add($listView)

```

Das Ergebnis entspricht konzeptionell:

```text
┌────────────────────────────────────────────────────────────┐
│ Name                    │ Typ         │ Größe              │
├─────────────────────────┼─────────────┼────────────────────┤
│ Dokument.txt            │ Textdatei   │ 12 KB              │
└─────────────────────────┴─────────────┴────────────────────┘

```

---

# Häufige Kombinationen

Für die praktische Verwendung sind einige Eigenschaftskombinationen besonders relevant:

### Tabellenansicht

```powershell
$listView.View = "Details"
$listView.FullRowSelect = $true
$listView.GridLines = $true

```

### Einzelauswahl

```powershell
$listView.MultiSelect = $false

```

### Checkbox-Liste

```powershell
$listView.CheckBoxes = $true
$listView.View = "Details"

```

### Liste mit Symbolen

```powershell
$listView.View = "SmallIcon"
$listView.SmallImageList = $imageList

```

### Große Symbolansicht

```powershell
$listView.View = "LargeIcon"
$listView.LargeImageList = $imageList

```

---

# Hinweise

- `ListView` ist besonders für strukturierte Listen und tabellarische Darstellungen geeignet.
- Für einfache Listen ohne zusätzliche Spalten ist `ListBox` meist einfacher.
- `Columns` werden hauptsächlich in der `Details`-Ansicht verwendet.
- Ein `ListViewItem` repräsentiert eine komplette Zeile.
- Zusätzliche Spalten eines Eintrags werden über `SubItems` definiert.
- `SelectedItems` enthält nur die aktuell ausgewählten Einträge.
- Bei großen Datenmengen sollte `BeginUpdate()` und `EndUpdate()` verwendet werden, um unnötige Neudarstellungen zu vermeiden.
- Für Bilder können `SmallImageList`, `LargeImageList` und `StateImageList` getrennt verwendet werden.
- `FullRowSelect` und `GridLines` haben ihre wesentliche Bedeutung in der `Details`-Ansicht.
- Mit `Groups` können Einträge zusätzlich logisch gruppiert werden.
- Über `LabelEdit` können Benutzer Einträge direkt im `ListView` umbenennen.

# Siehe auch

- `ListBox`
- `ImageList`
- `ListViewItem`
- `ListViewGroup`
- `ColumnHeader`
- `TableLayoutPanel`
- `FlowLayoutPanel`

# TabControl

Ein `<a href="https://doku.borinas.com/books/klassenwindowsforms/page/tabcontrol" title="TabControl">TabControl</a>` ist ein Container, der mehrere [`TabPage`](https://doku.borinas.com/books/klassenwindowsforms/page/tabpage "TabPage")-Instanzen verwaltet und zwischen ihnen umschaltet.   
Es stellt die Tabs (Reiter) dar und bestimmt, welche `TabPage` aktuell sichtbar ist.

---

### **Grundlagen**

Das `TabControl` ist **die Steuerung**, nicht der Inhalt.

- `TabControl` → verwaltet Tabs
- `TabPage` → enthält den eigentlichen Inhalt

#### **TabControl erstellen**

```powershell
# Klassisch
$tabControl = New-Object System.Windows.Forms.TabControl

# .NET-Style
$tabControl = [System.Windows.Forms.TabControl]::new()
```

#### **TabPage hinzufügen**


Ein `TabPage` wird nicht direkt zum `TabControl` hinzugefügt, sondern zur enthaltenen Sammlung `$tabControl.TabPages`.  
Die Sammlung `TabPages` stellt mehrere Methoden zum Hinzufügen von `TabPage`-Instanzen bereit:

- `TabPages.Add($tabPage1)` – Fügt das `TabPage` `$tabPage1` zur Sammlung hinzu
- `TabPages.AddRange(@($tabPage2, $tabPage3))` – Fügt mehrere `TabPage`-Instanzen gleichzeitig als Array hinzu
- `TabPages.Insert(0, $tabPage4)` – Fügt das `TabPage` an der gewünschten Position innerhalb der Sammlung ein

```powershell
$tabControl.TabPages.Add($tabPage1)

$tabControl.TabPages.AddRange(@(
    $tabPage2,
    $tabPage3
))

$tabControl.TabPages.Insert(0, $tabPage4)

# Technisch möglich, aber nicht empfohlen
$tabControl.Controls.Add($tabPage4)
$tabControl.Controls.AddRange(@(
    $tabPage5,
    $tabPage6
))
```

Über `Add()` kann zusätzlich direkt ein neues `TabPage` erstellt werden:

```powershell
# Erstellt ein neues TabPage
$tabControl.TabPages.Add("TabText")

# Erstellt ein neues TabPage mit Name + Text
$tabControl.TabPages.Add("TabName", "TabText")
```

#### **TabPage entfernen**

Ein `TabPage` kann aus dem `TabControl` mit der Referenz zum TabPage und `Remove()` oder über den Index mit `RemoveAt()` entfernt werden.

```powershell
$tabControl.TabPages.Remove($tabPage1) # mit Referenz
$tabControl.TabPages.RemoveAt(0) # mit Index
```

Mit `Clear()` werden alle `TabPage`-Instanzen entfernt.

```powershell
# Alle entfernen
$tabControl.TabPages.Clear()
```

#### **TabPage Auswahl/Zugriff**

Mit dem jeweiligen Index vom TabPage, kann in TabPages direkt auf das TabPage zugegriffen werden.

```powershell
# Zugriff auf einzelnes TabPage
$tabControl.TabPages[0]

# Aktiven Tab setzen
$tabControl.SelectedIndex = 0
$tabControl.SelectedTab = $tabPage1
```

---

## **Eigenschaften**

<details id="bkmrk-alignment-alignment-"><summary>Alignment</summary>

#### **Alignment**

**Typ** = `[Systems.Windows.Forms.TabAlignment]`

Der Wert von `Alignment` legt fest, an welcher Seite des `TabControl` die Tabs dargestellt werden. Standardmäßig ist diese Eigenschaft auf `Top` gesetzt, wodurch sich die Tabs oberhalb des Inhaltsbereichs befinden. Alternativ können die Tabs auch am unteren (`Bottom`), linken (`Left`) oder rechten (`Right`) Rand angezeigt werden. Die Position der Tabs beeinflusst lediglich deren Darstellung und hat keinen Einfluss auf die enthaltenen `TabPage`-Instanzen oder deren Funktionalität.

```powershell
$tabControl.Alignment = "Top"
```

</details><details id="bkmrk-anchor-anchor-typ-%3D-"><summary>Anchor</summary>

#### **Anchor**

**Typ** = `[Systems.Windows.Forms.AnchorStyles]`

Der Wert von `Anchor` legt fest, an welchen Rändern seines Parent-Containers ein Control verankert ist. Standardmäßig ist diese Eigenschaft auf `Top, Left` gesetzt, wodurch das Control seinen Abstand zum oberen und linken Rand beibehält. Wird die Größe des Parent-Containers verändert, passt das Control seine Position oder Größe entsprechend den festgelegten Verankerungen an.

Mehrere Verankerungen können kombiniert werden. Ist ein Control beispielsweise an `Left` und `Right` verankert, wird seine Breite automatisch angepasst, um den Abstand zu beiden Rändern beizubehalten. Durch die Kombination verschiedener Werte lässt sich das Verhalten eines Controls bei Größenänderungen flexibel steuern.

</details><details id="bkmrk-appearance-appearanc"><summary>Appearance</summary>

#### **Appearance**

**Typ** = \[System.Windows.Forms.TabAppearance\]

Der Wert von `Appearance` legt fest, wie die Tabs eines `TabControl` dargestellt werden. Standardmäßig ist diese Eigenschaft auf `Normal` gesetzt, wodurch die Tabs im klassischen Registerkarten-Stil angezeigt werden. Alternativ können die Tabs als Schaltflächen (`Buttons`) oder als flache Schaltflächen (`FlatButtons`) dargestellt werden.

- **Normal** → klassische Registerkarten
- **Buttons** → Tabs werden wie normale Schaltflächen dargestellt
- **FlatButtons** → Tabs werden wie flache Schaltflächen dargestellt

Die Eigenschaft beeinflusst ausschließlich das Erscheinungsbild der Tabs und hat keinen Einfluss auf die Funktionalität des `TabControl` oder der enthaltenen `TabPage`-Instanzen. Unabhängig von der gewählten Darstellung können Tabs weiterhin ausgewählt und gewechselt werden.

</details><details id="bkmrk-dock-dock-typ-%3D-%5Bsys"><summary>Dock</summary>

#### **Dock**

**Typ** = `[Systems.Windows.Forms.DockStyle]`

Der Wert von `Dock` legt fest, an welcher Seite seines Parent-Containers ein Control angedockt wird. Standardmäßig ist diese Eigenschaft auf `None` gesetzt, wodurch die Position und Größe des Controls ausschließlich durch dessen `Location`- und `Size`-Eigenschaften bestimmt werden. Alternativ kann das Control an den oberen (`Top`), unteren (`Bottom`), linken (`Left`) oder rechten (`Right`) Rand angedockt oder mit `Fill` auf die gesamte verfügbare Fläche des Parent-Containers ausgedehnt werden.

Im Gegensatz zu `Anchor` bestimmt `Dock` nicht die Abstände zu den Rändern, sondern übernimmt die automatische Positionierung und Größenanpassung des Controls. Wird beispielsweise `Fill` verwendet, füllt das Control den gesamten verfügbaren Bereich seines Parent-Containers aus.

</details><details id="bkmrk-drawmode-drawmode-ty"><summary>DrawMode</summary>

#### **DrawMode**

**Typ** = `[Systems.Windows.Forms.TabDrawMode]`

Der Wert von `DrawMode` legt fest, wie die Tabs des `TabControl` gezeichnet werden. Standardmäßig ist diese Eigenschaft auf `Normal` gesetzt, wodurch das Betriebssystem die Darstellung der Tabs vollständig übernimmt. Wird `DrawMode` auf `OwnerDrawFixed` gesetzt, ist der Entwickler für das Zeichnen der Tabs verantwortlich und kann deren Aussehen individuell gestalten.

Die Einstellung `OwnerDrawFixed` wird häufig verwendet, um eigene Farben, Schriftarten oder Symbole für Tabs darzustellen. Da die Tabs dabei selbst gezeichnet werden müssen, wird zusätzlich das `DrawItem`-Event benötigt, in dem die eigentliche Darstellung implementiert wird.

</details><details id="bkmrk-hottrack-hottrack-ty"><summary>HotTrack</summary>

#### **HotTrack**

**Typ** = `[System.Boolean]`

Der Wert von `HotTrack` legt fest, ob Tabs auf Mausbewegungen reagieren sollen. Standardmäßig ist diese Eigenschaft auf `False` gesetzt, wodurch Tabs ihr Aussehen beim Überfahren mit dem Mauszeiger nicht verändern. Wird `HotTrack` auf `True` gesetzt, hebt das `TabControl` den Tab unter dem Mauszeiger visuell hervor, um die Interaktion für den Benutzer deutlicher zu machen.

</details><details id="bkmrk-imagelist-imagelist-"><summary>ImageList</summary>

### **ImageList**

**Typ** = `[System.Windows.Forms.ImageList]`

Der Wert von `ImageList` legt die Bildersammlung fest, aus der das `TabControl` die Symbole für seine `TabPage`-Register bezieht.

Die Eigenschaft selbst bestimmt noch nicht, welches Bild angezeigt wird. Stattdessen wird für jede `TabPage` über deren Eigenschaften `ImageIndex` oder `ImageKey` festgelegt, welches Bild aus der `ImageList` verwendet werden soll.

```powershell
$imageList = [System.Windows.Forms.ImageList]::new()

$imageList.Images.Add("Home", [System.Drawing.Image]::FromFile("Home.png"))
$imageList.Images.Add("Settings", [System.Drawing.Image]::FromFile("Settings.png"))

$tabControl.ImageList = $imageList

$tabPage1.ImageKey = "Home"
$tabPage2.ImageKey = "Settings"

```

> 💡 **Hinweis**  
> Die Eigenschaft `ImageList` wird auf dem `TabControl` festgelegt. Welche Grafik angezeigt wird, bestimmen anschließend die Eigenschaften `ImageIndex` oder `ImageKey` der jeweiligen `TabPage`.

</details><details id="bkmrk-itemsize-itemsize-ty"><summary>ItemSize</summary>

#### **ItemSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `ItemSize` legt die Größe der einzelnen Tabs fest. Standardmäßig besitzt diese Eigenschaft den Wert `(Width=0, Height=0)`, wodurch die Größe der Tabs automatisch durch das `TabControl` bestimmt wird. Die Eigenschaft wird erst relevant, wenn `SizeMode` auf `Fixed` gesetzt ist. In diesem Fall verwendet das `TabControl` die in `ItemSize` festgelegte Breite und Höhe für alle Tabs.

</details><details id="bkmrk-multiline-multiline-"><summary>Multiline</summary>

#### **Multiline**

**Typ** = `[System.Boolean]`

Der Wert von `Multiline` legt fest, ob die Tabs auf mehrere Reihen verteilt werden dürfen. Standardmäßig ist diese Eigenschaft auf `False` gesetzt, wodurch alle Tabs in einer einzelnen Reihe dargestellt werden. Wird `Multiline` auf `True` gesetzt, erstellt das `TabControl` bei Platzmangel automatisch zusätzliche Reihen, sodass alle Tabs sichtbar bleiben können.

</details><details id="bkmrk-padding-padding-typ-"><summary>Padding</summary>

#### **Padding**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Padding` legt den Innenabstand innerhalb der Tab-Header fest. Standardmäßig ist diese Eigenschaft auf `(6, 3)` gesetzt. Dadurch wird zwischen dem Rand eines Tabs und dessen Inhalt, beispielsweise dem Text oder einem Icon, ein zusätzlicher Abstand eingefügt.

Die Eigenschaft beeinflusst nicht den Inhalt der enthaltenen `TabPage`-Instanzen, sondern ausschließlich die Darstellung der Tabs selbst. Durch größere Werte kann mehr Platz zwischen dem Rand eines Tabs und dessen Inhalt geschaffen werden, während kleinere Werte zu einer kompakteren Darstellung führen.

</details><details id="bkmrk-rowcount-rowcount-ty"><summary>RowCount</summary>

#### **RowCount**

**Typ** = `[System.Int32]`

Der Wert von `RowCount` gibt an, aus wie vielen Reihen die Tabs aktuell bestehen. Standardmäßig beträgt der Wert `0`, solange sich keine `TabPage` im `TabControl` befindet. Die Eigenschaft wird vom `TabControl` automatisch ermittelt und kann nicht direkt festgelegt werden. Besonders relevant ist `RowCount`, wenn `Multiline` auf `True` gesetzt ist, da die Tabs dann auf mehrere Reihen verteilt werden können.

</details><details id="bkmrk-selectedimageindex-s"><summary>SelectedImageIndex</summary>

#### **SelectedImageIndex**

**Typ** = `[System.Int32]`

Der Wert von `SelectedImageIndex` legt den Index des Bildes fest, das für den aktuell ausgewählten Tab verwendet werden soll. Standardmäßig ist diese Eigenschaft auf `-1` gesetzt, wodurch kein spezielles Bild für den aktiven Tab definiert ist. Die Bilder werden dabei aus der dem `TabControl` zugewiesenen `ImageList` bezogen.

Ist ein gültiger Bildindex angegeben, kann für den ausgewählten Tab ein anderes Symbol als für die übrigen Tabs dargestellt werden. Die Eigenschaft wird hauptsächlich in Verbindung mit einer `ImageList` verwendet und hat ohne zugewiesene Bilder keine sichtbare Auswirkung.

</details><details id="bkmrk-selectedindex-select"><summary>SelectedIndex</summary>

#### **SelectedIndex**

**Typ** = `[System.Int32]`

Der Wert von `SelectedIndex` entspricht dem Index des aktuell aktiven `TabPage`. Die `TabPages`-Collection ist 0-basiert, weshalb das erste `TabPage` den Index `0` besitzt. Befindet sich mindestens ein `TabPage` im `TabControl`, ist standardmäßig das erste `TabPage` aktiv. Ist die `TabPages`-Collection leer, beträgt der Wert von `SelectedIndex` `-1`.

</details><details id="bkmrk-selectedtab-selected"><summary>SelectedTab</summary>

#### **SelectedTab**

**Typ** = `[System.Windows.Forms.TabPage]`

Der Wert von `SelectedTab` enthält eine Referenz auf die aktuell aktive `TabPage` des `TabControl`. Standardmäßig ist diese Eigenschaft auf `$null` gesetzt, solange sich keine `TabPage` in der `TabPages`-Collection befindet. Sobald mindestens ein `TabPage` vorhanden ist, verweist `SelectedTab` auf das aktuell ausgewählte `TabPage`. Über diese Eigenschaft kann sowohl das aktive `TabPage` ausgelesen als auch ein anderes `TabPage` direkt ausgewählt werden.

</details><details id="bkmrk-showtooltips-showtoo"><summary>ShowToolTips</summary>

#### **ShowToolTips**

**Typ** = `[System.Boolean]`

Der Wert von `ShowToolTips` legt fest, ob für die Tabs eines `TabControl` Tooltips angezeigt werden dürfen. Standardmäßig ist diese Eigenschaft auf `$false` gesetzt, wodurch keine Tooltips dargestellt werden. Wird `ShowToolTips` auf `$true` gesetzt, können einzelnen `TabPage`-Instanzen Tooltip-Texte zugewiesen werden, die beim Überfahren des jeweiligen Tabs mit dem Mauszeiger angezeigt werden.

</details><details id="bkmrk-sizemode-sizemode-ty"><summary>SizeMode</summary>

#### **SizeMode**

**Typ** = `[Systems.Windows.Forms.TabSizeMode]`

Der Wert von `SizeMode` legt fest, wie die Größe der einzelnen Tabs bestimmt wird. Standardmäßig ist diese Eigenschaft auf `Normal` gesetzt, wodurch die Breite jedes Tabs automatisch anhand seines Inhalts berechnet wird. Wird `SizeMode` auf `Fixed` gesetzt, erhalten alle Tabs dieselbe Größe, die über die Eigenschaft `ItemSize` festgelegt werden kann.

</details><details id="bkmrk-tabpages-tabpages-ty"><summary>TabPages</summary>

#### **TabPages**

**Typ** = `[Systems.Windows.Forms.TabControl.TabPageCollection]`

Der Wert von `TabPages` enthält die Sammlung aller `TabPage`-Instanzen, die dem `TabControl` hinzugefügt wurden. Standardmäßig ist diese Sammlung leer. Über `TabPages` können `TabPage`-Instanzen hinzugefügt, entfernt oder anhand ihres Indexes bzw. ihrer Referenz abgerufen werden. Die Reihenfolge der Elemente innerhalb der Sammlung entspricht dabei der Reihenfolge der Tabs im `TabControl`.

</details>---

## **Methoden**

<details id="bkmrk-gettabrect%28%29-gettabr"><summary>GetTabRect</summary>

#### **GetTabRect()**

```PowerShell
$tabControl.GetTabRect( $Index )
```


##### **Parameter**

- **$Index** `[System.Int32]`  
    Index der `TabPage` in `TabControl`

##### **Beschreibung**

Die Methode `GetTabRect()` gibt die Position und Größe eines Tabs innerhalb des `TabControl` zurück.   
Über den angegebenen Index wird festgelegt, für welchen Tab die Informationen ermittelt werden sollen. Der Rückgabewert ist ein `Rectangle`, das die Position sowie die Breite und Höhe des entsprechenden Tab-Headers enthält. Die zurückgegebenen Koordinaten beziehen sich auf das TabControl selbst.

Die Methode wird häufig verwendet, um Mausklicks auf einzelne Tabs zu erkennen oder um eigene Zeichnungslogik mit `OwnerDrawFixed` umzusetzen.

##### **Rückgabe**

Gibt die Position und Größe des Tab-Headers der `TabPage` zurück.

**Rückgabetyp** `[System.Drawing.Rectangle]`

</details>### *TabPages* 

<details id="bkmrk-add%28%29-add%28%29-%24_.tabpa"><summary>Add</summary>

#### **Add**

```PowerShell
$_.TabPages.Add( $tabPage )
# → vorhandenes TabPage hinzufügen
```

Die Methode `Add()` fügt eine `TabPage` zur `TabPages`-Collection hinzu. Das `TabPage` wird dabei am Ende der Sammlung eingefügt und erscheint als neuer Tab im `TabControl`.

Nach dem Hinzufügen kann das `TabPage` über die `TabPages`-Collection, `SelectedIndex` oder `SelectedTab` verwendet werden.

```powershell
$_.TabPages.Add( "Text" )
# → Neues TabPage mit Text erstellen
```

Der übergebene Text wird dabei als Beschriftung des Tabs verwendet.

```PowerShell
$_.TabPages.Add( "Name", "Text" )
# → Neues TabPage mit Name und Text erstellen
```

Hierbei wird sowohl der interne `Name` als auch die sichtbare Beschriftung (`Text`) festgelegt.

Diese Varianten eignen sich für einfache Tabs, bei denen keine weiteren Eigenschaften unmittelbar gesetzt werden müssen.

**Rückgabetyp** `[void]`

</details><details id="bkmrk-addrange%28%29-addrange%28"><summary>AddRange</summary>

#### **AddRange()**

```PowerShell
$_.TabPages.AddRange( $tabPages )
```

Die Methode `AddRange()` fügt mehrere `TabPage`-Instanzen gleichzeitig zur `TabPages`-Collection hinzu.

Die Reihenfolge der Elemente im Array entspricht anschließend der Reihenfolge der Tabs im `TabControl`. Die Tabs werden dabei am Ende der vorhandenen Sammlung eingefügt.

</details><details id="bkmrk-clear%28%29-clear%28%29-%24_.t"><summary>Clear</summary>

#### **Clear()**

```PowerShell
$_.TabPages.Clear()
```

Die Methode `Clear()` entfernt alle `TabPage`-Instanzen aus der `TabPages`-Collection.

Nach dem Aufruf enthält das `TabControl` keine Tabs mehr. Existiert kein Tab mehr, besitzen Eigenschaften wie `SelectedIndex` den Wert `-1` und `SelectedTab` den Wert `$null`.

</details><details id="bkmrk-insert%28%29-insert%28%29-%24_"><summary>Insert</summary>

#### **Insert()**

```PowerShell
$_.TabPages.Insert( Index, $tabPage )
```

Die Methode `Insert()` fügt eine `TabPage` an einer bestimmten Position innerhalb der `TabPages`-Collection ein.

Bereits vorhandene Einträge werden ab dieser Position um eine Stelle nach hinten verschoben. Dadurch kann die Reihenfolge der Tabs gezielt beeinflusst werden.

</details><details id="bkmrk-remove%28%29-remove%28%29-%24_"><summary>Remove</summary>

#### **Remove()**

```PowerShell
$_.TabPages.Remove( $tabPage )
```

Die Methode `Remove()` entfernt eine bestimmte `TabPage` aus der `TabPages`-Collection.

Das `TabPage` selbst wird dabei nicht gelöscht, sondern lediglich aus dem `TabControl` entfernt. Es kann später erneut einer `TabPages`-Collection hinzugefügt werden.

**Rückgabetyp** `[void]`

</details><details id="bkmrk-removeat%28%29-removeat%28"><summary>RemoveAt</summary>

#### **RemoveAt()**

```PowerShell
$_.TabPages.RemoveAt( Index )
```

Die Methode `RemoveAt()` entfernt die `TabPage` an der angegebenen Position aus der `TabPages`-Collection.

Die verbleibenden Einträge rücken anschließend entsprechend nach vorne auf. Dadurch können sich die Indizes nachfolgender TabPages ändern.

</details>---

## **Events**

<details id="bkmrk-events-beispiel-even"><summary>Events</summary>

##### TabPage

- **Selecting** – Vor dem Wechsel zum TabPage
- **Selected** – Nach dem Wechsel zum TabPage
- **Deselecting** – Vor dem Verlassen vom TabPage
- **Deselected** – Nach dem Verlassen vom TabPage
- **SelectedIndexChanged** – Ausgewählter TabPage hat sich geändert

##### Cursor

- **Click** – Mausklick auf das TabControl
- **DoubleClick** – Doppelklick auf das TabControl
- **MouseDown** – Maustaste wurde auf dem TabControl gedrückt
- **MouseMove** – Maus wurde über dem TabControl bewegt
- **MouseUp** – Gedrückte Maustaste wurde auf dem TabControl losgelassen
- **MouseEnter** – Mauszeiger betritt den Bereich des TabControl
- **MouseLeave** – Mauszeiger verlässt den Bereich des TabControl
- **DragDrop** – Element wurde per Drag&amp;Drop auf dem TabControl abgelegt

##### Tastatur

- **KeyDown** – Taste wurde gedrückt während das TabControl den Fokus hat

##### Control

- **ControlAdded** – Dem TabControl wurde ein TabPage hinzugefügt
- **ControlRemoved** – Vom TabControl wurde ein TabPage entfernt

##### Design

- **Resize** – Größe des TabControl hat sich geändert
- **Paint** – TabControl wird neu gezeichnet

</details>```powershell
$tabControl.Add_*({
  param($sender, $e)
})
```

- `$sender` → Das TabControl selbst (=`$this`)
- `$e` *(EventArgs) →* Enthält die zum jeweiligen Event gehörenden Informationen.

---

### TabPage

Wenn du von **Tab A → Tab B** wechselst:

1. **`Deselecting`** *(TabControl)*  
    → bevor Tab A verlassen wird  
    → **kann abgebrochen werden** (`$_.Cancel = $true`)
2. **`Selecting`** *(TabControl)*  
    → bevor Tab B aktiviert wird  
    → **kann ebenfalls abgebrochen werden**

<p class="callout info">👉 Wenn hier keiner abbricht, geht’s weiter:</p>

3. **`Deselected`** *(TabControl)*  
    → Tab A wurde gerade deaktiviert
4. **`SelectedIndexChanged`** *(TabControl)*  
    → der Index hat sich geändert
5. **`Selected`** *(TabControl)*  
    → Tab B ist jetzt aktiv
6. **`Leave`** *(TabPage A)*  
    → Fokus verlässt alten Tab
7. **`Enter`** *(TabPage B)*  
    → Fokus betritt neuen Tab

<details id="bkmrk-selecting-selecting-"><summary>Selecting</summary>

#### **Selecting**

Das `Selecting`-Event wird **unmittelbar vor dem Wechsel auf einen anderen Tab** ausgelöst.

Zu diesem Zeitpunkt ist der neue Tab **noch nicht ausgewählt**. Über die Ereignisargumente kann ermittelt werden, welcher Tab ausgewählt werden soll. Da die Ereignisargumente die Eigenschaft `Cancel` besitzen, kann der Tabwechsel bei Bedarf verhindert werden.

Dieses Event eignet sich beispielsweise, um Eingaben zu validieren oder den Benutzer vor dem Verlassen eines Tabs zu warnen.

##### **Beispiel**

```powershell
$tabControl.Add_Selecting({
    param($sender, $e)

    if ($e.TabPage.Name -eq "tabSettings") {
        Write-Host "Einstellungen werden geöffnet."
    }
})

```

**Tabwechsel verhindern**

```powershell
$tabControl.Add_Selecting({
    param($sender, $e)

    if (-not $datenGespeichert) {
        $e.Cancel = $true
        [System.Windows.Forms.MessageBox]::Show(
            "Bitte speichern Sie zuerst Ihre Änderungen."
        )
    }
})

```

> 💡 **Hinweis**  
> Das `Selecting`-Event wird **vor** dem eigentlichen Tabwechsel ausgelöst. Soll lediglich auf einen bereits abgeschlossenen Tabwechsel reagiert werden, eignet sich stattdessen `Selected` oder `SelectedIndexChanged`.


</details><details id="bkmrk-selected-selected-da"><summary>Selected</summary>

#### **Selected**

Das `Selected`-Event wird **unmittelbar nach dem Wechsel auf einen anderen Tab** ausgelöst.

Zu diesem Zeitpunkt ist der neue Tab bereits ausgewählt und aktiv. Über die Ereignisargumente kann ermittelt werden, welcher `TabPage` ausgewählt wurde.

Dieses Event eignet sich beispielsweise, um Daten zu laden, die Oberfläche zu aktualisieren oder Aktionen auszuführen, sobald ein bestimmter Tab geöffnet wurde.

##### **Beispiel**

```powershell
$tabControl.Add_Selected({
    param($sender, $e)

    if ($e.TabPage.Name -eq "tabSettings") {
        Write-Host "Einstellungen wurden geöffnet."
    }
})
```

**Daten beim Öffnen eines Tabs laden**

```powershell
$tabControl.Add_Selected({
    param($sender, $e)

    if ($e.TabPage.Name -eq "tabLog") {
        Update-LogView
    }
})
```

> 💡 **Hinweis**  
> Das `Selected`-Event wird **nach** dem erfolgreichen Tabwechsel ausgelöst. Soll der Wechsel vorab geprüft oder verhindert werden, eignet sich stattdessen das `Selecting`-Event.

</details>#### **SelectedIndexChanged**

Wird ausgelöst, **nachdem sich der ausgewählte Tab geändert hat**

- ❌ Kein `$e.TabPage`
- ✅ `$sender.SelectedTab` → aktuell aktiver Tab
- ✅ `$sender.SelectedIndex` → Index des aktiven Tabs

<details id="bkmrk-%24sender%2C-%24e-%24sender-"><summary>param</summary>

#### `<strong>$sender</strong>`

- `SelectedTab` → aktuell aktiver Tab (`TabPage`)
- `SelectedIndex` → Index davon
- `TabPages` → alle Tabs (Collection)
- `TabCount` → Anzahl Tabs
- `Name` → Name vom Control
- `Enabled` → ob aktiv
- `Visible` → sichtbar oder nicht

#### `<strong>$e</strong>`

Ein Standard-EventArgs-Objekt, ohne nützliche Zusatzinfos

</details>```powershell
$tabControl.Add_SelectedIndexChanged({
    param($sender, $e)

    # Aktueller Tab
    $currentTab = $sender.SelectedTab

    Write-Host "Aktiver Tab: $($currentTab.Name)"
})
```

#### **Deselecting**

Vor dem Verlassen vom TabPage → kann noch abgebrochen werden

<details id="bkmrk-param-%24sender%C2%A0-das-t-1"><summary>param</summary>

#### **`$sender`** 

Das `TabControl` selbst (=`$this`)

#### `<strong>$e</strong>`

- `TabPage` → das TabPage, von dem gewechselt werden soll
- `TabPageIndex` → Index vom TabPage, von dem gewechselt werden soll
- `Cancel` → Mit `$true` wird der Wechsel verhindert

</details>```powershell
$tabControl.Add_Deselecting({
    param($sender, $e)

    # Aktueller Tab (der verlassen wird)
    $currentTab = $e.TabPage

    # Beispiel: Verhindere Verlassen wenn noch Auswahl vorhanden
    if ($currentTab.Name -eq "PackageTab" -and $checkedListBox.CheckedItems.Count -gt 0) {
        Write-Host "Du hast noch Auswahl!"

        $e.Cancel = $true
    }
})
```

#### **Deselected**

Nach dem Verlassen eines Tabs → ideal zum Zurücksetzen von UI

<details id="bkmrk-param-%24e-%28eventargs%29"><summary>param</summary>

`$e` *(EventArgs)  
•* `$e.TabPage` → das TabPage, das verlassen wurde

</details>```powershell
$tabControl.Add_Deselected({
    param($sender, $e)

    # Verlassener Tab
    $oldTab = $e.TabPage

    if ($oldTab.Name -eq "PackageTab") {

        # CheckedListBox zurücksetzen
        for ($i = 0; $i -lt $checkedListBox.Items.Count; $i++) {
            $checkedListBox.SetItemChecked($i, $false)
        }

        # ListBox zurücksetzen
        $listBox.ClearSelected()
    }
})
```

---

### Cursor

#### **Click**

Klick auf das Control (selten relevant)

#### **MouseDown**

Klick einer beliebigen Maustaste auf dem TabControl

<details id="bkmrk-param-%24e.button-%E2%80%93-ge"><summary>param</summary>

- `$e.Button` – gedrückte Maustaste → `[MouseButtons]::Left`
- `$e.Location` – Position des Mausklicks

</details>##### **ControlAdded / ControlRemoved**

Wenn TabPages hinzugefügt oder entfernt werden. Wird ausgelöst, wenn ein TabPage zur TabPages-Collection  
hinzugefügt oder daraus entfernt wird.

---

## **Tipps &amp; Tricks**

#### Typische Stolperfallen

- **Tab wird nicht angezeigt**  
    → nicht zur `TabPages`-Collection hinzugefügt
- **Events greifen nicht**  
    → falsches Event verwendet (`Selecting` vs. `SelectedIndexChanged`)
- **Layout wirkt falsch**  
    → `Dock` / `Anchor` nicht sauber gesetzt
- **Icons fehlen**  
    → `ImageList` nicht gesetzt oder falscher Index

---

### Mentales Modell

Das `TabControl` ist ein **Container mit Umschalter-Logik**.

Es zeigt genau eine `TabPage` gleichzeitig  
und verwaltet nur, welche sichtbar ist.

---

### Wann sinnvoll?

- Strukturierung komplexer Inhalte
- Einstellungen / Optionen
- Platz sparen

---

### Wann vermeiden?

- Häufiges Hin- und Herspringen notwendig
- Linearer Workflow
- Stark voneinander abhängige Inhalte

---

# Panel

Ein `Panel` ist ein einfacher Container für andere Controls. Es dient dazu, mehrere Controls logisch und visuell zu einer Einheit zusammenzufassen.

Im Gegensatz zu einem `TableLayoutPanel` besitzt ein `Panel` kein eigenes Raster oder automatisches Layoutsystem. Die enthaltenen Controls werden grundsätzlich über ihre `Location`- und `Size`-Eigenschaften positioniert und dimensioniert.

Ein Panel kann selbst wiederum in anderen Containern liegen, wodurch sich komplexe Benutzeroberflächen aus mehreren verschachtelten Bereichen aufbauen lassen.

---

# **Grundlagen**

Das `Panel` ist ein **Container für Controls**.

```text
Panel
├── Label
├── TextBox
├── Button
└── CheckBox
```

Vergleich mit anderen Container-Controls:

- **Panel** → freie Positionierung über Location
- **FlowLayoutPanel** → automatische Anordnung hintereinander
- **TableLayoutPanel** → Anordnung in Zeilen und Spalten


### Panel erstellen

```powershell
# Klassisch
$panel = New-Object System.Windows.Forms.Panel

# .NET-Style
$panel = [System.Windows.Forms.Panel]::new()
```

### Panel hinzufügen

Ein `Panel` wird wie jedes andere Control der `Controls`-Collection seines Parent-Containers hinzugefügt.

```powershell
$form.Controls.Add($panel)

# oder

$tabPage.Controls.Add($panel)
```

### Controls hinzufügen

Controls werden über die `Controls`-Collection des Panels hinzugefügt.

```powershell
$panel.Controls.Add($button)
$panel.Controls.Add($label)
$panel.Controls.Add($textBox)

```

Die Position der Controls wird anschließend über deren `Location` festgelegt.

```powershell
$button.Location  = "10, 10"
$label.Location   = "10, 50"
$textBox.Location = "100, 50"
```

### Controls entfernen

Ein Control kann über seine Referenz entfernt werden

```powershell
$panel.Controls.Remove($button)
```

oder mit seinen Index in der `Controls`-Collection

```powershell
$panel.Controls.RemoveAt(0)
```

Mit `Clear()` werden alle enthaltenen Controls entfernt.

```powershell
$panel.Controls.Clear()
```

---

## **Eigenschaften**

<table id="bkmrk-eigenschaft-beschrei"><thead><tr><th>Eigenschaft</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`AutoScroll`</td><td>Aktiviert automatisch Scrollleisten, wenn der Inhalt größer als das Panel ist.</td></tr><tr><td>`AutoSize`</td><td>Passt die Größe automatisch an den Inhalt an.</td></tr><tr><td>`AutoSizeMode`</td><td>Bestimmt, in welche Richtung sich das Panel bei `AutoSize` anpassen darf.</td></tr><tr><td>`BackColor`</td><td>Legt die Hintergrundfarbe des Panels fest.</td></tr><tr><td>`BorderStyle`</td><td>Bestimmt, ob und wie das Panel einen Rahmen darstellt.</td></tr><tr><td>`Dock`</td><td>Dockt das Panel an einer Seite seines Parent-Containers an.</td></tr><tr><td>`Anchor`</td><td>Verankert das Panel an den Rändern seines Parent-Containers.</td></tr><tr><td>`Padding`</td><td>Legt den Innenabstand zwischen Panelrand und enthaltenen Controls fest.</td></tr><tr><td>`Margin`</td><td>Legt den äußeren Abstand des Panels zu anderen Controls fest.</td></tr><tr><td>`Controls`</td><td>Enthält alle Controls, die sich innerhalb des Panels befinden.</td></tr><tr><td>`Location`</td><td>Bestimmt die Position des Panels im Parent-Container.</td></tr><tr><td>`Size`</td><td>Bestimmt Breite und Höhe des Panels.</td></tr><tr><td>`MinimumSize`</td><td>Definiert die minimal zulässige Größe des Panels.</td></tr><tr><td>`MaximumSize`</td><td>Definiert die maximal zulässige Größe des Panels.</td></tr><tr><td>`Name`</td><td>Legt den internen Namen des Panels fest.</td></tr><tr><td>`Visible`</td><td>Legt fest, ob das Panel sichtbar ist.</td></tr><tr><td>`Enabled`</td><td>Legt fest, ob das Panel und seine enthaltenen Controls aktiviert sind.</td></tr></tbody></table>

---

<details id="bkmrk-autoscroll-typ-%3D-%5Bsy"><summary>AutoScroll</summary>

Typ = `[System.Boolean]`

Die Eigenschaft `AutoScroll` legt fest, ob das Panel automatisch Scrollleisten anzeigt, wenn sein Inhalt größer als der sichtbare Bereich ist.

Standardmäßig ist `AutoScroll` auf `False` gesetzt.

Wird die Eigenschaft auf `True` gesetzt, erscheinen horizontale und/oder vertikale Scrollleisten automatisch, sobald der Inhalt nicht mehr vollständig in das Panel passt.

```powershell
$panel.AutoScroll = $true

```

</details><details id="bkmrk-autosize-typ-%3D%C2%A0%5Bsyst"><summary>AutoSize</summary>

Typ = `[System.Boolean]`

Die Eigenschaft `AutoSize` legt fest, ob das Panel seine Größe automatisch an seinen Inhalt anpasst.

Standardmäßig besitzt diese Eigenschaft den Wert `False`.

Ist `AutoSize` aktiviert, wird die benötigte Größe des Panels anhand seiner enthaltenen Controls und deren Layoutinformationen bestimmt.

```powershell
$panel.AutoSize = $true

```

</details><details id="bkmrk-autosizemode-typ-%3D%C2%A0%5B"><summary>AutoSizeMode</summary>

Typ = `[System.Windows.Forms.AutoSizeMode]`

Die Eigenschaft `AutoSizeMode` bestimmt, wie sich das Panel bei aktiviertem `AutoSize` an seinen Inhalt anpasst.

Es stehen zwei Werte zur Verfügung:

- `GrowAndShrink` → Das Panel kann seine Größe sowohl vergrößern als auch verkleinern.
- `GrowOnly` → Das Panel kann nur größer werden, aber nicht automatisch kleiner.

Standardmäßig ist `GrowOnly` eingestellt.

```powershell
$panel.AutoSize = $true
$panel.AutoSizeMode = "GrowAndShrink"

```

</details><details id="bkmrk-backcolor-typ-%3D%C2%A0%5Bsys"><summary>BackColor</summary>

Typ = `[System.Drawing.Color]`

Die Eigenschaft `BackColor` legt die Hintergrundfarbe des Panels fest.

```powershell
$panel.BackColor = "LightBlue"

```

Die Hintergrundfarbe betrifft ausschließlich die vom Panel selbst dargestellte Fläche. Die enthaltenen Controls behalten grundsätzlich ihre eigene Darstellung.

</details><details id="bkmrk-borderstyle-typ-%3D%C2%A0%5Bs"><summary>BorderStyle</summary>

Typ = `[System.Windows.Forms.BorderStyle]`

Die Eigenschaft `BorderStyle` bestimmt, ob das Panel einen Rahmen darstellt.

Mögliche Werte:

- `None` → kein Rahmen
- `FixedSingle` → einfacher Rahmen
- `Fixed3D` → dreidimensionaler Rahmen

Standardmäßig besitzt `BorderStyle` den Wert `None`.

```powershell
$panel.BorderStyle = "FixedSingle"

```

Der Rahmen dient hauptsächlich der visuellen Abgrenzung des Panels und verändert nicht die grundlegende Funktion des Containers.

</details><details id="bkmrk-controls-typ-%3D%C2%A0%5Bsyst"><summary>Controls</summary>

Typ = `[System.Windows.Forms.Control+ControlCollection]`

Die Eigenschaft `Controls` enthält alle Controls, die direkt innerhalb des Panels liegen.

Über diese Collection können Controls hinzugefügt, entfernt oder abgerufen werden.

```powershell
$panel.Controls.Add($button)

$panel.Controls.Remove($button)

$panel.Controls.Clear()

```

Ein Control kann über seinen Index abgerufen werden:

```powershell
$panel.Controls[0]

```

Die Collection enthält dabei nur die **direkt** im Panel enthaltenen Controls. Controls, die wiederum innerhalb eines anderen Panels liegen, gehören nicht direkt zu dieser Collection.

</details><details id="bkmrk-dock-typ-%3D%C2%A0%5Bsystem.w"><summary>Dock</summary>

Typ = `[System.Windows.Forms.DockStyle]`

Die Eigenschaft `Dock` legt fest, wie das Panel innerhalb seines Parent-Containers angedockt wird.

Standardmäßig besitzt `Dock` den Wert `None`.

Alternativ kann das Panel an einer Seite angedockt werden:

- `Top`
- `Bottom`
- `Left`
- `Right`
- `Fill`

Mit `Fill` nimmt das Panel den gesamten verfügbaren Bereich des Parent-Containers ein.

```powershell
$panel.Dock = "Fill"

```

Dies ist besonders praktisch, wenn ein Panel als Arbeitsbereich innerhalb eines `Form`, `TabPage` oder eines anderen Containers verwendet wird.

</details><details id="bkmrk-anchor-typ-%3D%C2%A0%5Bsystem"><summary>Anchor</summary>

Typ = `[System.Windows.Forms.AnchorStyles]`

Die Eigenschaft `Anchor` legt fest, an welchen Rändern des Parent-Containers das Panel verankert bleibt.

Standardmäßig ist das Panel an `Top` und `Left` verankert.

```powershell
$panel.Anchor = "Top, Left, Right"

```

Wird ein Panel beispielsweise an `Left` und `Right` verankert, passt sich seine Breite an die Größe des Parent-Containers an.

Im Gegensatz zu `Dock` behält `Anchor` die Abstände zu den angegebenen Rändern bei.

</details><details id="bkmrk-padding-typ-%3D%C2%A0%5Bsyste"><summary>Padding</summary>

Typ = `[System.Windows.Forms.Padding]`

Die Eigenschaft `Padding` legt den Innenabstand zwischen dem Rand des Panels und seinen enthaltenen Controls fest.

```powershell
$panel.Padding = 10

```

Dadurch beginnen enthaltene Controls nicht direkt am Rand des Panels.

Der Unterschied zu `Margin`:

```text
Margin  → Abstand außerhalb des Panels
Padding → Abstand innerhalb des Panels

```

</details><details id="bkmrk-margin-typ-%3D%C2%A0%5Bsystem"><summary>Margin</summary>

Typ = `[System.Windows.Forms.Padding]`

Die Eigenschaft `Margin` legt den äußeren Abstand des Panels zu anderen Controls fest.

```powershell
$panel.Margin = 10

```

Die Eigenschaft wird insbesondere von Layout-Containern wie `FlowLayoutPanel` und `TableLayoutPanel` berücksichtigt.

</details><details id="bkmrk-location-typ-%3D%C2%A0%5Bsyst"><summary>Location</summary>

Typ = `[System.Drawing.Point]`

Die Eigenschaft `Location` bestimmt die Position des Panels innerhalb seines Parent-Containers.

Die Position wird über die X- und Y-Koordinate angegeben.

```powershell
$panel.Location = "20, 40"

```

Da ein normales Panel kein eigenes Layoutsystem besitzt, ist `Location` insbesondere für die Positionierung der enthaltenen Controls relevant.

```powershell
$button.Location = "10, 10"
$label.Location  = "10, 50"

```

</details><details id="bkmrk-size-typ-%3D%C2%A0%5Bsystem.d"><summary>Size</summary>

Typ = `[System.Drawing.Size]`

Die Eigenschaft `Size` bestimmt die Breite und Höhe des Panels.

```powershell
$panel.Size = "300, 200"

```

Die Größe kann auch durch `Dock`, `Anchor` oder `AutoSize` beeinflusst werden.

</details><details id="bkmrk-visible-typ-%3D%C2%A0%5Bsyste"><summary>Visible</summary>

Typ = `[System.Boolean]`

Die Eigenschaft `Visible` legt fest, ob das Panel sichtbar dargestellt wird.

```powershell
$panel.Visible = $false

```

Wird das Panel ausgeblendet, werden auch seine enthaltenen Controls nicht sichtbar dargestellt.

</details><details id="bkmrk-enabled-typ-%3D%C2%A0%5Bsyste"><summary>Enabled</summary>

Typ = `[System.Boolean]`

Die Eigenschaft `Enabled` legt fest, ob das Panel aktiviert ist.

```powershell
$panel.Enabled = $false

```

Wird ein Panel deaktiviert, können auch seine enthaltenen Controls nicht mehr über die Benutzeroberfläche bedient werden.

<table id="bkmrk-methode-beschreibung"><thead><tr><th>  
</th></tr></thead></table>

</details>

---

# **Methoden**

| Methode | Beschreibgung
| :-----: | :-
| BringToFront() | Bringt das Panel innerhalb seines Parent-Containers in den Vordergrund
| SendToBack() | Verschiebt das Panel innerhalb seines Parent-Containers in den Hintergrund
| ScrollControllIntoView() | Scrollt das angegebene Control in den sichtbaren Bereich
| PerformLayout() | Erzwingt eine erneute Layoutberechnung des Panels
| Refresh() | Aktualisiert die Darstellung des Panels

## BringToFront()

Die Methode `BringToFront()` bringt das Panel innerhalb seines Parent-Containers in den Vordergrund.

Dies beeinflusst die Z-Reihenfolge der Controls.

```powershell
$panel.BringToFront()
```

Befinden sich mehrere Controls übereinander, kann dadurch festgelegt werden, welches Control sichtbar über den anderen liegt.


## SendToBack()

Die Methode `SendToBack()` verschiebt das Panel innerhalb seines Parent-Containers in den Hintergrund.

```powershell
$panel.SendToBack()
```

Dadurch können andere Controls, die sich an derselben Position befinden, vor dem Panel dargestellt werden.

## ScrollControlIntoView()

Die Methode `ScrollControlIntoView()` sorgt dafür, dass ein angegebenes Control innerhalb des Panels sichtbar wird.

Sie ist insbesondere relevant, wenn `AutoScroll` aktiviert ist.

```powershell
$panel.AutoScroll = $true

$panel.ScrollControlIntoView($button)
```

Befindet sich das angegebene Control außerhalb des momentan sichtbaren Bereichs, wird das Panel entsprechend gescrollt.

## PerformLayout()

Die Methode `PerformLayout()` erzwingt eine sofortige Neuberechnung des Layouts.

```powershell
$panel.PerformLayout()
```

Dies kann nützlich sein, wenn mehrere Eigenschaften oder Controls verändert wurden und die Layoutberechnung anschließend unmittelbar durchgeführt werden soll.

## Refresh()

Die Methode `Refresh()` aktualisiert die Darstellung des Panels.

```powershell
$panel.Refresh()

```

Dabei wird das Panel neu gezeichnet.

---

## **Events**

<details>
  <summary>Übersicht</summary>
<table id="bkmrk-event-beschreibung-c"><thead><tr><th>Event</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`ControlAdded`</td><td>Wird ausgelöst, wenn ein Control zum Panel hinzugefügt wird.</td></tr><tr><td>`ControlRemoved`</td><td>Wird ausgelöst, wenn ein Control aus dem Panel entfernt wird.</td></tr><tr><td>`Layout`</td><td>Wird ausgelöst, wenn das Layout des Panels neu berechnet wird.</td></tr><tr><td>`Paint`</td><td>Wird ausgelöst, wenn das Panel gezeichnet bzw. neu gezeichnet wird.</td></tr><tr><td>`Resize`</td><td>Wird ausgelöst, wenn sich die Größe des Panels ändert.</td></tr><tr><td>`Enter`</td><td>Wird ausgelöst, wenn das Panel bzw. ein darin enthaltener Fokusbereich betreten wird.</td></tr><tr><td>`Leave`</td><td>Wird ausgelöst, wenn das Panel bzw. ein darin enthaltener Fokusbereich verlassen wird.</td></tr></tbody></table>
</details>

### ControlAdded

Wird ausgelöst, sobald ein Control zum Panel hinzugefügt wird.

```powershell
$panel.Add_ControlAdded({
    param($sender, $e)

    Write-Host "Control hinzugefügt: $($e.Control.Name)"
})
```

### ControlRemoved

Wird ausgelöst, sobald ein Control aus dem Panel entfernt wird.

```powershell
$panel.Add_ControlRemoved({
    param($sender, $e)

    Write-Host "Control entfernt: $($e.Control.Name)"
})
```

### Layout

Das Event wird ausgelöst, wenn das Panel sein Layout neu berechnet.

Dies kann beispielsweise durch folgende Änderungen geschehen:

- Größe des Panels geändert
- Controls hinzugefügt oder entfernt
- Größe eines enthaltenen Controls geändert
- Änderungen an `Dock`
- Änderungen an `Anchor`
- Änderungen an `Padding`

```powershell
$panel.Add_Layout({
    param($sender, $e)

    Write-Host "Layout aktualisiert"
})
```

### Resize

Wird ausgelöst, wenn sich die Größe des Panels ändert.

```powershell
$panel.Add_Resize({
    param($sender, $e)

    Write-Host "Panel-Größe geändert"
})
```

### Paint

Wird ausgelöst, wenn das Panel neu gezeichnet wird.

```powershell
$panel.Add_Paint({
    param($sender, $e)

    # Eigene Zeichenlogik
})
```

### Typische Stolperfallen

- **Control ist nicht sichtbar**  
    → Das Control wurde nicht zur `Controls`-Collection des Panels hinzugefügt.
- **Control sitzt an der falschen Position**  
    → `Location` des Controls überprüfen.
- **Panel passt sich nicht an den Parent an**  
    → `Dock` oder `Anchor` überprüfen.
- **Panel wächst nicht mit seinem Inhalt**  
    → `AutoSize` aktivieren.
- **Inhalt ist außerhalb des sichtbaren Bereichs nicht erreichbar**  
    → `AutoScroll` aktivieren.
- **Controls liegen nicht mit dem gewünschten Abstand am Rand**  
    → `Padding` des Panels überprüfen.
- **Panel liegt hinter einem anderen Control**  
    → `BringToFront()` oder `SendToBack()` verwenden.

### Mentales Modell

Das `Panel` ist ein **Container ohne eigenes Layoutsystem**.

Es stellt hauptsächlich einen abgegrenzten Bereich bereit, in dem andere Controls platziert werden können.

```text
Parent
│
└── Panel
    ├── Label
    ├── TextBox
    └── Button
```

Die Positionierung der enthaltenen Controls erfolgt grundsätzlich über deren eigene Eigenschaften:

```text
Panel
│
├── Location
├── Size
└── Controls
      │
      ├── Button.Location
      ├── Label.Location
      └── TextBox.Location
```

Damit unterscheidet sich das Panel grundlegend von einem `TableLayoutPanel`: Das Panel **ordnet nichts automatisch an**, sondern stellt lediglich den Container bereit. Das entspricht auch dem von dir bereits verwendeten Vergleich in der `TableLayoutPanel`-Doku.

### Wann sinnvoll?

Ein `Panel` eignet sich besonders für:

- Gruppierung zusammengehöriger Controls
- Aufbau mehrteiliger Benutzeroberflächen
- Verschachtelung von UI-Bereichen
- Bereiche, die gemeinsam ein- oder ausgeblendet werden sollen
- eigene Layoutlogik über `Location` und `Size`
- scrollbare Inhaltsbereiche

### Wann anderes Control verwenden?

Ein anderes Container-Control ist sinnvoller, wenn die Positionierung automatisch erfolgen soll:

- `FlowLayoutPanel` → Controls automatisch hintereinander anordnen
- `TableLayoutPanel` → Controls in Zeilen und Spalten anordnen
- `TabControl` → zwischen mehreren Inhaltsbereichen umschalten

Das ist eigentlich die wichtigste Erkenntnis der ganzen Seite: **Panel ist der einfache Container.** Es macht nicht heimlich Layoutmagie im Hintergrund. Und genau deshalb ist es oft das angenehmste Control von allen. Welch seltene Ausnahme in der Windows-Forms-Welt.

# GroupBox

Eine `<a href="https://doku.borinas.com/books/klassenwindowsforms/page/groupbox" title="GroupBox">GroupBox</a>` ist ein Container zur visuellen Gruppierung von Controls.  
Sie dient hauptsächlich dazu, zusammengehörige Eingabefelder, Optionen oder Steuerelemente optisch voneinander abzugrenzen.

Der Text der `GroupBox` wird als Überschrift im Rahmen dargestellt

---

## **Grundlagen**

Das `GroupBox` selbst enthält keine besondere Logik.

- `GroupBox` → Container mit Beschriftung
- enthaltene Controls → eigentlicher Inhalt

#### **GroupBox erstellen**

```powershell
# Klassisch
$groupBox = New-Object System.Windows.Forms.GroupBox

# .NET-Style
$groupBox = [System.Windows.Forms.GroupBox]::new()

```

#### **Controls hinzufügen**

Controls werden über die `Controls`-Collection hinzugefügt.

```powershell
$groupBox.Controls.Add($textBox)

$groupBox.Controls.AddRange(@(
    $label,
    $button
))

```

#### **Controls entfernen**

```powershell
$groupBox.Controls.Remove($textBox)

$groupBox.Controls.Clear()

```

---

## **Eigenschaften**

<table border="1" id="bkmrk-eigenschaft-beschrei" style="border-collapse: collapse; width: 58.0952%; height: 298px;"><colgroup><col style="width: 20.5293%;"></col><col style="width: 79.4708%;"></col></colgroup><thead><tr style="height: 29.8px;"><td style="height: 29.8px;">**Eigenschaft**</td><td style="height: 29.8px;">**Beschreibung**</td></tr></thead><tbody><tr style="height: 29.8px;"><td style="height: 29.8px;">**Anchor**</td><td style="height: 29.8px;">Verankerung an den Rändern des Parent-Containers</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**AutoSize**</td><td style="height: 29.8px;">Größe automatisch an Inhalt anpassen</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**Controls**</td><td style="height: 29.8px;">Enthaltene Controls</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**Dock**</td><td style="height: 29.8px;">Automatische Ausrichtung im Parent-Container</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**Enabled**</td><td style="height: 29.8px;">Aktiviert oder deaktiviert enthaltene Controls</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**Font**</td><td style="height: 29.8px;">Schriftart der Überschrift</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**ForeColor**</td><td style="height: 29.8px;">Farbe der Überschrift</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**Padding**</td><td style="height: 29.8px;">Innenabstand für enthaltene Controls</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">**Text**</td><td style="height: 29.8px;">Überschrift der GroupBox</td></tr><tr><td>**Visible**</td><td>Sichtbarkeit der GroupBox</td></tr></tbody></table>

<details id="bkmrk-controls-controls%C2%A0%5Bs"><summary>Controls</summary>

#### **Controls** \[System.Windows.Forms.Control.ControlCollection\]

Enthält alle Controls, die sich innerhalb der GroupBox befinden.

```powershell
$groupBox.Controls.Add($button)

```


</details><details id="bkmrk-enabled-enabled%C2%A0%5Bsys"><summary>Enabled</summary>

#### **Enabled** \[System.Boolean\]

Legt fest, ob die GroupBox aktiviert ist.

Wird `Enabled` auf `$false` gesetzt, werden auch alle enthaltenen Controls deaktiviert.

```powershell
$groupBox.Enabled = $false

```


</details><details id="bkmrk-padding-padding%C2%A0%5Bsys"><summary>Padding</summary>

#### **Padding** \[System.Windows.Forms.Padding\]

Legt den Innenabstand fest, der zwischen Rahmen und enthaltenen Controls eingehalten wird.

```powershell
$groupBox.Padding = 10

```

---


</details><details id="bkmrk-text-text-%5Bsystem.st"><summary>Text</summary>

#### **Text** \[System.String\]

Der Wert von `Text` bestimmt die Beschriftung der GroupBox.

Standardmäßig ist der Wert leer.

```powershell
$groupBox.Text = "Office Installation"

```


</details>---

# **Methoden**

| Methode  | Beschreibung
| :------: | -
| Add      | Fügt ein Control hinzu
| AddRange | Fügt mehrere Controls hinzu
| Remove   | Entfernt ein Control
| Clear    | Entfernt alle Controls

---

### Add()

```powershell
$_.Controls.Add($control)
```

Die Methode `Add()` fügt ein Control zur `Controls`-Collection der GroupBox hinzu.

---

### AddRange()

```powershell
$_.Controls.AddRange( @($label, $textbox, $button) )
```

Die Methode `AddRange()` fügt mehrere Controls gleichzeitig zur `Controls`-Collection hinzu.

---

### Remove()

```powershell
$_.Controls.Remove($control)
```

Die Methode `Remove()` entfernt ein bestimmtes Control aus der GroupBox.

---

### Clear()

```powershell
$_.Controls.Clear()
```

Die Methode `Clear()` entfernt alle enthaltenen Controls.

---

# **Events**

| Event          | Beschreibung
| :------------: | -
| Click          | Mausklick auf die GroupBox
| DoubleClick    | Doppelklick auf die GroupBox
| MouseDown      | Maustaste wurde gedrückt
| MouseUp        | Maustaste wurde losgelassen
| MouseMove      | Maus wurde bewegt
| MouseEnter     | Mauszeiger betritt die GroupBox
| MouseLeave     | Mauszeiger verlässt die GroupBox
| Enter          | Fokus betritt die GroupBox
| Leave          | Fokus verlässt die GroupBox
| ControlAdded   | Ein Control wurde hinzugefügt
| ControlRemoved | Ein Control wurde entfernt
| Resize         | Größe wurde geändert
| Paint          | GroupBox wird neu gezeichnet


```powershell
$groupBox.Add_*({
    param($sender, $e)
})
```

- `$sender` → Die GroupBox selbst (`$this`)
- `$e` → EventArgs des jeweiligen Events

---

### ControlAdded / ControlRemoved

Werden ausgelöst, wenn Controls zur `Controls`-Collection hinzugefügt oder daraus entfernt werden.

```powershell
$groupBox.Add_ControlAdded({
    param($sender, $e)

    Write-Host "$($e.Control.Name) wurde hinzugefügt"
})

```

---

## **Tipps &amp; Tricks**

### Typische Stolperfallen

- **Controls erscheinen nicht**
    
    
    - Position liegt außerhalb der GroupBox
- **Alle Controls werden deaktiviert**
    
    
    - `GroupBox.Enabled = $false`
- **Padding erzeugt kein automatisches Layout**
    
    
    - Controls müssen weiterhin selbst positioniert werden
- **GroupBox für Layout verwendet**
    
    
    - Für komplexe Layouts meist besser: `Panel`, `FlowLayoutPanel` oder `TableLayoutPanel`

---

## Mentales Modell

Die `GroupBox` ist ein **Container mit Beschriftung**.

Sie gruppiert Controls optisch und logisch, besitzt jedoch keine eigene Inhaltslogik.

---

## Wann sinnvoll?

- Einstellungen gruppieren
- Formulare strukturieren
- Optionen zusammenfassen
- RadioButtons logisch gruppieren

---

## Wann vermeiden?

- Komplexe Layouts
- Scrollbare Bereiche
- Dynamische Containerlogik
- Wenn lediglich ein Rahmen benötigt wird

# FlowLayoutPanel

Ein `FlowLayoutPanel` ist ein Layout-Container, der seine enthaltenen Controls automatisch hintereinander anordnet.

Im Gegensatz zu einem normalen `Panel` müssen die enthaltenen Controls nicht über ihre `Location` positioniert werden. Das `FlowLayoutPanel` übernimmt die Anordnung anhand der festgelegten Flussrichtung.

Wird der verfügbare Platz überschritten, können die Controls automatisch in eine neue Zeile beziehungsweise Spalte umgebrochen werden.

```text
Panel
→ freie Positionierung über Location

FlowLayoutPanel
→ automatische Anordnung hintereinander

TableLayoutPanel
→ Anordnung in Zeilen und Spalten
````

---

## Grundlagen

Ein `FlowLayoutPanel` eignet sich besonders für Benutzeroberflächen, bei denen Controls dynamisch nebeneinander oder untereinander angeordnet werden sollen.

Typische Einsatzgebiete sind beispielsweise:

* Button-Leisten
* dynamische Listen von Controls
* Werkzeugleisten
* Filter- und Einstellungsbereiche
* Karten- oder Kachelansichten
* automatisch umbrechende Control-Gruppen

### FlowLayoutPanel erstellen

```powershell
# Klassisch
$flow = New-Object System.Windows.Forms.FlowLayoutPanel

# .NET-Style
$flow = [System.Windows.Forms.FlowLayoutPanel]::new()
```

### Controls hinzufügen

Controls werden wie bei anderen Container-Controls über die `Controls`-Collection hinzugefügt.

```powershell
$flow.Controls.Add($button)
$flow.Controls.Add($label)
$flow.Controls.Add($textBox)
```

Die Position der Controls wird anschließend automatisch durch das Layoutsystem bestimmt.

### Flussrichtung

Standardmäßig werden Controls von links nach rechts angeordnet.

```powershell
$flow.FlowDirection = "LeftToRight"
```

Alternativ kann die Anordnung beispielsweise von oben nach unten erfolgen:

```powershell
$flow.FlowDirection = "TopDown"
```

### Automatischer Umbruch

Ist `WrapContents` aktiviert, werden Controls automatisch in eine neue Zeile oder Spalte verschoben, sobald der verfügbare Platz nicht mehr ausreicht.

```powershell
$flow.WrapContents = $true
```

Dadurch kann sich das Layout automatisch an die Größe des Containers anpassen.

---

# Eigenschaften

| Eigenschaft     | Beschreibung                                                                                |
| --------------- | ------------------------------------------------------------------------------------------- |
| `AutoScroll`    | Aktiviert automatisch Scrollleisten, wenn der Inhalt den verfügbaren Bereich überschreitet. |
| `AutoSize`      | Passt die Größe des Panels automatisch an seinen Inhalt an.                                 |
| `BackColor`     | Legt die Hintergrundfarbe des Panels fest.                                                  |
| `BorderStyle`   | Bestimmt die Darstellung des Rahmens.                                                       |
| `Controls`      | Enthält alle Controls des Panels.                                                           |
| `Dock`          | Dockt das Panel an einer Seite seines Parent-Containers an.                                 |
| `FlowDirection` | Bestimmt die Richtung, in der Controls angeordnet werden.                                   |
| `Location`      | Bestimmt die Position des Panels im Parent-Container.                                       |
| `Margin`        | Legt den äußeren Abstand des Panels zu seinem Parent fest.                                  |
| `MaximumSize`   | Definiert die maximal zulässige Größe.                                                      |
| `MinimumSize`   | Definiert die minimal zulässige Größe.                                                      |
| `Name`          | Legt den internen Namen des Panels fest.                                                    |
| `Padding`       | Legt den Innenabstand zwischen Rand und enthaltenen Controls fest.                          |
| `Size`          | Bestimmt Breite und Höhe des Panels.                                                        |
| `WrapContents`  | Legt fest, ob Controls automatisch in eine neue Zeile oder Spalte umgebrochen werden.       |
| `Visible`       | Legt fest, ob das Panel sichtbar ist.                                                       |
| `Enabled`       | Legt fest, ob das Panel und seine enthaltenen Controls verwendet werden können.             |

---

<details>
<summary>AutoScroll</summary>

### **AutoScroll**

**Typ** = `[System.Boolean]`

Der Wert von `AutoScroll` legt fest, ob das `FlowLayoutPanel` automatisch Scrollleisten anzeigt, wenn der enthaltene Inhalt größer als der sichtbare Bereich ist.

Standardmäßig besitzt diese Eigenschaft den Wert `False`.

Ist `AutoScroll` auf `True` gesetzt, werden horizontale und/oder vertikale Scrollleisten angezeigt, sobald die enthaltenen Controls nicht mehr vollständig in den verfügbaren Bereich passen.

```powershell
$flow.AutoScroll = $true
```

> 💡 **Hinweis**
> `AutoScroll` ist besonders nützlich, wenn die Anzahl oder Größe der enthaltenen Controls zur Laufzeit variieren kann.

</details>

---

<details>
<summary>AutoSize</summary>

### **AutoSize**

**Typ** = `[System.Boolean]`

Der Wert von `AutoSize` legt fest, ob sich die Größe des `FlowLayoutPanel` automatisch an seinen Inhalt anpasst.

Standardmäßig besitzt diese Eigenschaft den Wert `False`.

Ist `AutoSize` aktiviert, kann das Panel seine Größe anhand der enthaltenen Controls und deren Layout bestimmen.

```powershell
$flow.AutoSize = $true
```

> 💡 **Hinweis**
> Das tatsächliche Verhalten von `AutoSize` hängt unter anderem von `FlowDirection`, `WrapContents`, `Dock` und den Größen der enthaltenen Controls ab.

</details>

---

<details>
<summary>BackColor</summary>

### **BackColor**

**Typ** = `[System.Drawing.Color]`

Der Wert von `BackColor` legt die Hintergrundfarbe des `FlowLayoutPanel` fest.

```powershell
$flow.BackColor = "WhiteSmoke"
```

</details>

---

<details>
<summary>BorderStyle</summary>

### **BorderStyle**

**Typ** = `[System.Windows.Forms.BorderStyle]`

Der Wert von `BorderStyle` bestimmt, ob und wie das `FlowLayoutPanel` einen sichtbaren Rahmen besitzt.

Folgende Werte stehen zur Verfügung:

* **None** → kein Rahmen
* **FixedSingle** → einfacher Rahmen
* **Fixed3D** → dreidimensionaler Rahmen

```powershell
$flow.BorderStyle = "FixedSingle"
```

</details>

---

<details>
<summary>Controls</summary>

### **Controls**

**Typ** = `[System.Windows.Forms.Control.ControlCollection]`

Die Eigenschaft `Controls` enthält alle Controls, die sich innerhalb des `FlowLayoutPanel` befinden.

Über diese Collection können Controls hinzugefügt, entfernt oder ausgelesen werden.

```powershell
$flow.Controls.Add($button)
```

Mehrere Controls können beispielsweise über eine Schleife hinzugefügt werden:

```powershell
foreach ($button in $buttons) {
    $flow.Controls.Add($button)
}
```

Die Reihenfolge der Controls innerhalb der Collection entspricht dabei grundsätzlich auch der Reihenfolge, in der sie vom Layoutsystem angeordnet werden.

</details>

---

<details>
<summary>Dock</summary>

### **Dock**

**Typ** = `[System.Windows.Forms.DockStyle]`

Der Wert von `Dock` legt fest, an welcher Seite seines Parent-Containers das `FlowLayoutPanel` angedockt wird.

```powershell
$flow.Dock = "Fill"
```

Mit `Fill` nimmt das Panel den gesamten verfügbaren Bereich seines Parent-Containers ein.

Weitere mögliche Werte sind:

* `None`
* `Top`
* `Bottom`
* `Left`
* `Right`
* `Fill`

> 💡 **Hinweis**
> Wird `Dock = "Fill"` verwendet, passt sich das Panel automatisch an die Größe des Parent-Containers an. Dadurch kann insbesondere `WrapContents` seine Wirkung beim Vergrößern oder Verkleinern des Fensters zeigen.

</details>

---

<details>
<summary>FlowDirection</summary>

### **FlowDirection**

**Typ** = `[System.Windows.Forms.FlowDirection]`

Der Wert von `FlowDirection` bestimmt die Richtung, in der die enthaltenen Controls angeordnet werden.

Standardmäßig besitzt diese Eigenschaft den Wert `LeftToRight`.

Folgende Werte stehen zur Verfügung:

| Wert          | Beschreibung                                      |
| ------------- | ------------------------------------------------- |
| `LeftToRight` | Controls werden von links nach rechts angeordnet. |
| `RightToLeft` | Controls werden von rechts nach links angeordnet. |
| `TopDown`     | Controls werden von oben nach unten angeordnet.   |
| `BottomUp`    | Controls werden von unten nach oben angeordnet.   |

```powershell
$flow.FlowDirection = "LeftToRight"
```

Beispiel für eine vertikale Anordnung:

```powershell
$flow.FlowDirection = "TopDown"
```

> 💡 **Hinweis**
> Zusammen mit `WrapContents` bestimmt `FlowDirection`, in welche Richtung das Layout zunächst fließt und wann ein Umbruch erfolgt.

</details>

---

<details>
<summary>Location</summary>

### **Location**

**Typ** = `[System.Drawing.Point]`

Der Wert von `Location` legt die Position des `FlowLayoutPanel` innerhalb seines Parent-Containers fest.

Die Position wird über die X- und Y-Koordinate angegeben.

```powershell
$flow.Location = "20, 40"
```

> 💡 **Hinweis**
> Wird zusätzlich `Dock` verwendet, wird die Position durch das Layoutsystem bestimmt.

</details>

---

<details>
<summary>Margin</summary>

### **Margin**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Margin` legt den äußeren Abstand des `FlowLayoutPanel` zu seinem Parent-Container fest.

```powershell
$flow.Margin = [System.Windows.Forms.Padding]::new(10)
```

Bei den enthaltenen Controls besitzt `Margin` eine zusätzliche Bedeutung: Das `FlowLayoutPanel` berücksichtigt den Außenabstand der einzelnen Controls bei der automatischen Anordnung.

```powershell
$button.Margin = [System.Windows.Forms.Padding]::new(5)
```

Dadurch entsteht beispielsweise ein Abstand von 5 Pixeln zwischen den einzelnen Controls.

</details>

---

<details>
<summary>MaximumSize</summary>

### **MaximumSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `MaximumSize` legt die maximal zulässige Größe des `FlowLayoutPanel` fest.

Standardmäßig besitzt diese Eigenschaft den Wert `(0,0)`, wodurch keine Größenbegrenzung besteht.

```powershell
$flow.MaximumSize = "600, 400"
```

</details>

---

<details>
<summary>MinimumSize</summary>

### **MinimumSize**

**Typ** = `[System.Drawing.Size]`

Der Wert von `MinimumSize` legt die minimal zulässige Größe des `FlowLayoutPanel` fest.

```powershell
$flow.MinimumSize = "200, 100"
```

Wird versucht, das Panel kleiner als die angegebene Mindestgröße zu machen, bleibt diese Mindestgröße erhalten.

</details>

---

<details>
<summary>Name</summary>

### **Name**

**Typ** = `[System.String]`

Der Wert von `Name` legt den internen Namen des `FlowLayoutPanel` fest.

Der Name dient ausschließlich zur Identifikation innerhalb des Programms.

```powershell
$flow.Name = "flowButtons"
```

</details>

---

<details>
<summary>Padding</summary>

### **Padding**

**Typ** = `[System.Windows.Forms.Padding]`

Der Wert von `Padding` legt den Innenabstand zwischen dem Rand des `FlowLayoutPanel` und seinen enthaltenen Controls fest.

```powershell
$flow.Padding = [System.Windows.Forms.Padding]::new(10)
```

Dadurch werden die enthaltenen Controls mit einem Abstand von 10 Pixeln zum Rand des Panels angeordnet.

> 💡 **Hinweis**
> `Padding` betrifft den Innenbereich des Panels, während `Margin` den Außenabstand des Panels beziehungsweise der enthaltenen Controls beschreibt.

</details>

---

<details>
<summary>Size</summary>

### **Size**

**Typ** = `[System.Drawing.Size]`

Der Wert von `Size` legt die Breite und Höhe des `FlowLayoutPanel` fest.

```powershell
$flow.Size = "500, 300"
```

Die tatsächliche Größe kann durch `AutoSize`, `Dock` oder andere Layoutmechanismen beeinflusst werden.

</details>

---

<details>
<summary>WrapContents</summary>

### **WrapContents**

**Typ** = `[System.Boolean]`

Der Wert von `WrapContents` legt fest, ob Controls automatisch in eine neue Zeile beziehungsweise Spalte umgebrochen werden, wenn der verfügbare Platz nicht mehr ausreicht.

Standardmäßig besitzt diese Eigenschaft den Wert `True`.

```powershell
$flow.WrapContents = $true
```

Bei einem horizontalen Layout:

```text
[Button 1] [Button 2] [Button 3]
[Button 4] [Button 5] [Button 6]
```

Wird `WrapContents` deaktiviert, versucht das `FlowLayoutPanel`, alle Controls in der ursprünglichen Flussrichtung anzuordnen.

```powershell
$flow.WrapContents = $false
```

Bei `LeftToRight` werden die Controls dadurch beispielsweise weiterhin horizontal angeordnet, auch wenn dadurch der verfügbare Bereich überschritten wird.

> 💡 **Hinweis**
> `WrapContents` wirkt immer zusammen mit `FlowDirection`. Die Flussrichtung bestimmt, wohin die Controls zunächst angeordnet werden, während `WrapContents` bestimmt, ob bei fehlendem Platz ein Umbruch erfolgt.

</details>

---

<details>
<summary>Visible</summary>

### **Visible**

**Typ** = `[System.Boolean]`

Der Wert von `Visible` legt fest, ob das `FlowLayoutPanel` sichtbar dargestellt wird.

```powershell
$flow.Visible = $false
```

</details>

---

<details>
<summary>Enabled</summary>

### **Enabled**

**Typ** = `[System.Boolean]`

Der Wert von `Enabled` legt fest, ob das `FlowLayoutPanel` aktiviert ist.

Standardmäßig besitzt diese Eigenschaft den Wert `True`.

```powershell
$flow.Enabled = $false
```

Wird das Panel deaktiviert, werden auch die enthaltenen Controls entsprechend deaktiviert dargestellt beziehungsweise reagieren nicht mehr auf Eingaben.

</details>

---

# Methoden

## Übersicht

| Methode          | Beschreibung                                                                                          |
| ---------------- | ----------------------------------------------------------------------------------------------------- |
| `GetFlowBreak()` | Ermittelt, ob nach einem bestimmten Control ein Zeilen- beziehungsweise Spaltenumbruch erfolgt.       |
| `SetFlowBreak()` | Legt fest, ob nach einem bestimmten Control ein Zeilen- beziehungsweise Spaltenumbruch erfolgen soll. |

---

<details>
<summary>GetFlowBreak()</summary>

### **GetFlowBreak()**

Die Methode `GetFlowBreak()` ermittelt, ob für ein bestimmtes Control ein manueller Umbruch festgelegt wurde.

```powershell
$flow.GetFlowBreak($button)
```

Der Rückgabewert ist ein `Boolean`.

```text
True  → Nach dem Control erfolgt ein Umbruch.
False → Es erfolgt kein manueller Umbruch.
```

Beispiel:

```powershell
if ($flow.GetFlowBreak($button)) {
    Write-Host "Nach dem Button beginnt eine neue Zeile."
}
```

</details>

---

<details>
<summary>SetFlowBreak()</summary>

### **SetFlowBreak()**

Die Methode `SetFlowBreak()` legt fest, ob nach einem bestimmten Control ein manueller Umbruch erfolgen soll.

```powershell
$flow.SetFlowBreak($button, $true)
```

Der erste Parameter bestimmt das Control, nach dem der Umbruch erfolgen soll.

Der zweite Parameter bestimmt, ob der Umbruch aktiviert oder deaktiviert wird.

```powershell
$flow.SetFlowBreak($button, $true)
```

→ Nach dem Button beginnt ein neuer Layoutabschnitt.

```powershell
$flow.SetFlowBreak($button, $false)
```

→ Der manuelle Umbruch wird wieder entfernt.

### Beispiel

```powershell
$flow = [System.Windows.Forms.FlowLayoutPanel]::new()

$button1 = [System.Windows.Forms.Button]::new()
$button1.Text = "Button 1"

$button2 = [System.Windows.Forms.Button]::new()
$button2.Text = "Button 2"

$button3 = [System.Windows.Forms.Button]::new()
$button3.Text = "Button 3"

$flow.Controls.Add($button1)
$flow.Controls.Add($button2)
$flow.Controls.Add($button3)

$flow.SetFlowBreak($button2, $true)
```

Das Layout kann dadurch beispielsweise so aussehen:

```text
[Button 1] [Button 2]
[Button 3]
```

> 💡 **Hinweis**
> `SetFlowBreak()` ist besonders praktisch, wenn einzelne Controls unabhängig von der verfügbaren Breite einen neuen Layoutabschnitt beginnen sollen.

</details>

---

# Events

Das `FlowLayoutPanel` besitzt die üblichen Events eines Windows-Forms-Controls. Besonders relevant sind Events, die durch Änderungen am enthaltenen Layout oder an der `Controls`-Collection ausgelöst werden.

| Event            | Beschreibung                                                   |
| ---------------- | -------------------------------------------------------------- |
| `ControlAdded`   | Wird ausgelöst, wenn ein Control hinzugefügt wird.             |
| `ControlRemoved` | Wird ausgelöst, wenn ein Control entfernt wird.                |
| `Layout`         | Wird ausgelöst, wenn das Layout des Panels neu berechnet wird. |
| `SizeChanged`    | Wird ausgelöst, wenn sich die Größe des Panels ändert.         |

---

<details>
<summary>ControlAdded</summary>

### **ControlAdded**

Das Event `ControlAdded` wird ausgelöst, sobald ein Control zur `Controls`-Collection des `FlowLayoutPanel` hinzugefügt wurde.

```powershell
$flow.Add_ControlAdded({
    param($sender, $e)

    Write-Host "Control hinzugefügt: $($e.Control.Name)"
})
```

Das Event kann beispielsweise verwendet werden, um neu hinzugefügte Controls automatisch zu konfigurieren.

</details>

---

<details>
<summary>ControlRemoved</summary>

### **ControlRemoved**

Das Event `ControlRemoved` wird ausgelöst, sobald ein Control aus der `Controls`-Collection entfernt wurde.

```powershell
$flow.Add_ControlRemoved({
    param($sender, $e)

    Write-Host "Control entfernt: $($e.Control.Name)"
})
```

</details>

---

<details>
<summary>Layout</summary>

### **Layout**

Das Event `Layout` wird ausgelöst, wenn das Layout des `FlowLayoutPanel` neu berechnet wird.

```powershell
$flow.Add_Layout({
    param($sender, $e)

    Write-Host "Layout wurde aktualisiert."
})
```

Das Event kann beispielsweise verwendet werden, wenn auf Änderungen der Größe oder Anordnung der enthaltenen Controls reagiert werden soll.

> ⚠️ **Hinweis**
> Das `Layout`-Event kann relativ häufig ausgelöst werden. Aufwendige Operationen sollten daher nicht unkontrolliert innerhalb dieses Events ausgeführt werden.

</details>

---

# Beispiel

Das folgende Beispiel erstellt ein `FlowLayoutPanel`, das mehrere Buttons automatisch horizontal anordnet und bei Bedarf in eine neue Zeile umbricht.

```powershell
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = [System.Windows.Forms.Form]::new()
$form.Text = "FlowLayoutPanel"
$form.Size = "500, 300"

$flow = [System.Windows.Forms.FlowLayoutPanel]::new()
$flow.Dock = "Fill"
$flow.Padding = [System.Windows.Forms.Padding]::new(10)
$flow.FlowDirection = "LeftToRight"
$flow.WrapContents = $true
$flow.AutoScroll = $true

$form.Controls.Add($flow)

foreach ($i in 1..10) {

    $button = [System.Windows.Forms.Button]::new()
    $button.Text = "Button $i"
    $button.Size = "100, 40"
    $button.Margin = [System.Windows.Forms.Padding]::new(5)

    $flow.Controls.Add($button)
}

$form.ShowDialog()
```

Das Layout passt sich automatisch an die verfügbare Breite des Fensters an:

```text
┌─────────────────────────────────────┐
│ [Button 1] [Button 2] [Button 3]   │
│ [Button 4] [Button 5] [Button 6]   │
│ [Button 7] [Button 8] [Button 9]   │
│ [Button 10]                         │
└─────────────────────────────────────┘
```

Wird das Fenster breiter, können mehr Controls in einer Zeile dargestellt werden. Wird es schmaler, werden die Controls automatisch in weitere Zeilen umgebrochen.

---

# FlowLayoutPanel vs. andere Container

| Control            | Anordnung                             |
| ------------------ | ------------------------------------- |
| `Panel`            | Freie Positionierung über `Location`  |
| `FlowLayoutPanel`  | Automatische Anordnung hintereinander |
| `TableLayoutPanel` | Anordnung in Zeilen und Spalten       |
| `TabPage`          | Container für den Inhalt eines Tabs   |

Ein `FlowLayoutPanel` ist damit besonders dann geeignet, wenn Controls **in einer bestimmten Reihenfolge automatisch angeordnet**, aber nicht an feste Zeilen oder Spalten gebunden werden sollen.

---

# Hinweise

* `FlowDirection` bestimmt die Richtung des Layouts.
* `WrapContents` bestimmt, ob bei fehlendem Platz automatisch umgebrochen wird.
* `Margin` der enthaltenen Controls wird beim Layout berücksichtigt.
* `Padding` des `FlowLayoutPanel` bestimmt den Abstand der Controls zum Rand.
* `SetFlowBreak()` ermöglicht manuelle Umbrüche unabhängig vom verfügbaren Platz.
* `AutoScroll` kann verwendet werden, wenn der Inhalt größer als der sichtbare Bereich werden kann.
* `AutoSize` und `WrapContents` können sich gegenseitig stark auf das Layoutverhalten auswirken.
* `Location` der enthaltenen Controls sollte bei Verwendung eines `FlowLayoutPanel` normalerweise nicht manuell gesetzt werden, da ihre Position vom Layoutsystem bestimmt wird.

# TableLayoutPanel

Ein `TableLayoutPanel` ist ein Layout-Container, der seine enthaltenen Controls in einem **Raster aus Zeilen und Spalten** anordnet.

Im Gegensatz zu einem normalen `Panel` werden Controls nicht über ihre `Location` positioniert, sondern einer bestimmten Zelle innerhalb des Rasters zugewiesen. Das `TableLayoutPanel` übernimmt anschließend automatisch die Positionierung und Größenanpassung aller enthaltenen Controls.

---

## **Grundlagen**

Ein `TableLayoutPanel` organisiert Controls in einem **Tabellenlayout**.

- `Panel` → freie Positionierung über `Location`
- `FlowLayoutPanel` → automatische Anordnung hintereinander
- `TableLayoutPanel` → Anordnung in Zeilen und Spalten

#### TableLayoutPanel erstellen

```powershell
# Klassisch
$table = New-Object System.Windows.Forms.TableLayoutPanel

# .NET-Style
$table = [System.Windows.Forms.TableLayoutPanel]::new()
```

#### Controls hinzufügen

```powershell
$table.Controls.Add($button)
```

oder direkt in eine bestimmte Zelle

```powershell
$table.Controls.Add($button, 1, 0) # Spalte 1, Zeile 0
```

#### Zeilen und Spalten festlegen

```powershell
$table.ColumnCount = 2
$table.RowCount    = 3

```

---

## **Eigenschaften**

<table id="bkmrk-eigenschaft-beschrei"><thead><tr><th>Eigenschaft</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`ColumnCount`</td><td>Anzahl der Spalten.</td></tr><tr><td>`RowCount`</td><td>Anzahl der Zeilen.</td></tr><tr><td>`ColumnStyles`</td><td>Definiert Breite jeder Spalte.</td></tr><tr><td>`RowStyles`</td><td>Definiert Höhe jeder Zeile.</td></tr><tr><td>`GrowStyle`</td><td>Legt fest, wie neue Zeilen oder Spalten entstehen.</td></tr><tr><td>`CellBorderStyle`</td><td>Zeichnet Rahmen zwischen den Zellen.</td></tr><tr><td>`Dock`</td><td>Dockt das Panel an den Parent an.</td></tr><tr><td>`Anchor`</td><td>Verankert das Panel am Parent.</td></tr><tr><td>`AutoSize`</td><td>Passt die Größe automatisch an.</td></tr><tr><td>`AutoScroll`</td><td>Aktiviert Scrollleisten.</td></tr><tr><td>`BackColor`</td><td>Hintergrundfarbe.</td></tr><tr><td>`Padding`</td><td>Innenabstand.</td></tr><tr><td>`Margin`</td><td>Außenabstand.</td></tr><tr><td>`Name`</td><td>Interner Name.</td></tr><tr><td>`Location`</td><td>Position des Panels.</td></tr><tr><td>`Size`</td><td>Größe des Panels.</td></tr><tr><td>`Visible`</td><td>Sichtbarkeit.</td></tr><tr><td>`Enabled`</td><td>Aktiviert bzw. deaktiviert das Panel.</td></tr></tbody></table>

<details id="bkmrk-autoscroll-autoscrol"><summary>AutoScroll</summary>

### **AutoScroll**

<table style="border-collapse:collapse;width:35.1852%;"><colgroup><col style="width:50.1683%;"></col><col style="width:50.1683%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Boolean</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">False</span>`</td></tr></tbody></table>

Die Eigenschaft `AutoScroll` legt fest, ob das `TableLayoutPanel` automatisch Scrollleisten anzeigt, wenn der Inhalt größer ist als der sichtbare Bereich.

Ist `AutoScroll` auf `True` gesetzt, erscheinen horizontale und/oder vertikale Scrollleisten nur dann, wenn sie tatsächlich benötigt werden. Dadurch bleiben auch Controls erreichbar, die sich außerhalb des aktuell sichtbaren Bereichs befinden.

**Beispiel:**

```powershell
$table.AutoScroll = $true
```

Sind mehr Controls vorhanden, als im verfügbaren Bereich angezeigt werden können, fügt das `TableLayoutPanel` automatisch die erforderlichen Scrollleisten hinzu.

**Hinweis:**

- `AutoScroll` ist standardmäßig deaktiviert (`False`).
- Scrollleisten werden nur angezeigt, wenn der Inhalt die sichtbare Größe des `TableLayoutPanel` überschreitet.
- Besonders nützlich bei dynamischen Benutzeroberflächen, deren Anzahl an Controls zur Laufzeit variieren kann.

</details><details id="bkmrk-autosize-autosize-ty"><summary>AutoSize</summary>

### **AutoSize**

<table style="border-collapse:collapse;width:35.1852%;"><colgroup><col style="width:50.1683%;"></col><col style="width:50.1683%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Boolean</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">False</span>`</td></tr></tbody></table>

Passt die Größe automatisch an den Inhalt an.

**Beispiel:**

```powershell
$table.AutoSize = $true
```

</details><details id="bkmrk-cellborderstyle-cell"><summary>CellBorderStyle</summary>

### **CellBorderStyle**

<table style="border-collapse:collapse;width:71.7284%;"><colgroup><col style="width:23.3209%;"></col><col style="width:76.6824%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Windows.Forms.TableLayoutPanelCellBorderStyle</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">None</span>`</td></tr></tbody></table>

Legt fest, ob zwischen den Zellen Rahmen gezeichnet werden.

Mögliche Werte

- `None`
- `Single`
- `Inset`
- `Outset`
- `InsetDouble`
- `OutsetDouble`

**Beispiel:**

```powershell
$table.CellBorderStyle = "Single"
```

</details><details id="bkmrk-columncount-columnco"><summary>ColumnCount</summary>

### **ColumnCount**

<table style="border-collapse:collapse;width:35.1852%;"><colgroup><col style="width:50.1683%;"></col><col style="width:50.1683%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Int32</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">0</span>`</td></tr></tbody></table>

Legt fest, aus wie vielen Spalten das Layout besteht.

**Beispiel:**

```powershell
$table.ColumnCount = 3
```

</details><details id="bkmrk-columnstyles-columns"><summary>ColumnStyles</summary>

### **ColumnStyles**

<table style="border-collapse:collapse;width:68.8889%;"><colgroup><col style="width:21.319%;"></col><col style="width:78.681%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Windows.Forms.TableLayoutColumnStyleCollection</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">leere Sammlung</td></tr></tbody></table>

Bestimmt die Breite jeder einzelnen Spalte.

Es gibt drei verschiedene Größenarten:

<table><thead><tr><th>Größe</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`Absolute`</td><td>Feste Pixelgröße</td></tr><tr><td>`Percent`</td><td>Prozentuale Verteilung</td></tr><tr><td>`AutoSize`</td><td>Größe richtet sich nach dem Inhalt</td></tr></tbody></table>

**Beispiel:**

```powershell
$table.ColumnStyles.Add(
    [System.Windows.Forms.ColumnStyle]::new("Percent",50)
)

$table.ColumnStyles.Add(
    [System.Windows.Forms.ColumnStyle]::new("Percent",50)
)
```

</details><details id="bkmrk-dock-dock-typ-%3D-syst"><summary>Dock</summary>

### **Dock**

<table style="border-collapse:collapse;width:46.5432%;"><colgroup><col style="width:32.7586%;"></col><col style="width:67.2414%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Windows.Forms.DockStyle</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">None</span>`</td></tr></tbody></table>

Legt fest, wie das TableLayoutPanel innerhalb seines Parent-Containers angedockt wird.

**Beispiel:**

```powershell
$table.Dock = "Fill"
```

Dies ist die häufigste Einstellung.

</details><details id="bkmrk-growstyle-growstyle-"><summary>GrowStyle</summary>

### **GrowStyle**

<table style="border-collapse:collapse;width:70.4938%;"><colgroup><col style="width:21.6287%;"></col><col style="width:78.3713%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Windows.Forms.TableLayoutPanelGrowStyle</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">AddRows</span>`</td></tr></tbody></table>

Legt fest, wie das Panel reagiert, wenn mehr Controls hinzugefügt werden als Zellen vorhanden sind.

Mögliche Werte

- `AddRows`
- `AddColumns`
- `FixedSize`

**Beispiel:**

```powershell
$table.GrowStyle = "AddRows"
```

Bei `FixedSize` wird eine Ausnahme ausgelöst, wenn kein Platz mehr vorhanden ist.

</details><details id="bkmrk-rowcount-rowcount-ty"><summary>RowCount</summary>

### **RowCount**

<table style="border-collapse:collapse;width:35.1852%;"><colgroup><col style="width:50.1683%;"></col><col style="width:50.1683%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Int32</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">`<span style="color:rgb(35,111,161);">0</span>`</td></tr></tbody></table>

Legt die Anzahl der Zeilen fest, die das `TableLayoutPanel` enthält.

Zusammen mit `ColumnCount` bestimmt diese Eigenschaft die Größe des Tabellenrasters. Jede Zeile kann anschließend über die Eigenschaft `RowStyles` individuell konfiguriert werden.

**Beispiel:**

```powershell
$table.RowCount = 3
```

Das `TableLayoutPanel` besitzt nun drei Zeilen.

**Hinweis:**

- `RowCount` legt lediglich die Anzahl der Zeilen fest. Die Höhe der einzelnen Zeilen wird über `RowStyles` bestimmt.
- Zusammen mit `ColumnCount` ergibt sich die Gesamtzahl der verfügbaren Zellen.
- Wird `GrowStyle` auf `AddRows` gesetzt, kann das `TableLayoutPanel` bei Bedarf automatisch weitere Zeilen hinzufügen.

</details><details id="bkmrk-rowstyles-rowstyles-"><summary>RowStyles</summary>

### **RowStyles**

<table style="border-collapse:collapse;width:70.4938%;"><colgroup><col style="width:21.6287%;"></col><col style="width:78.3713%;"></col></colgroup><tbody><tr><td>**Typ**</td><td class="align-left">`<span style="color:rgb(132,63,161);">System.Windows.Forms.TableLayoutRowStyleCollection</span>`</td></tr><tr><td>**Standardwert**</td><td class="align-left">leere Sammlung</td></tr></tbody></table>

Bestimmt die Höhe jeder Zeile.

Auch hier stehen

- `Absolute`
- `Percent`
- `AutoSize`

zur Verfügung.

**Beispiel:**

```powershell
$table.RowStyles.Add(
    [System.Windows.Forms.RowStyle]::new("AutoSize")
)
```

</details>---

## **Methoden**

<table id="bkmrk-methode-beschreibung"><thead><tr><th>Methode</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`GetControlFromPosition()`</td><td>Liefert das Control einer bestimmten Zelle.</td></tr><tr><td>`GetPositionFromControl()`</td><td>Liefert die Position eines Controls.</td></tr><tr><td>`GetColumn()`</td><td>Liefert die Spalte eines Controls.</td></tr><tr><td>`GetRow()`</td><td>Liefert die Zeile eines Controls.</td></tr><tr><td>`SetColumn()`</td><td>Verschiebt ein Control in eine andere Spalte.</td></tr><tr><td>`SetRow()`</td><td>Verschiebt ein Control in eine andere Zeile.</td></tr><tr><td>`SetColumnSpan()`</td><td>Lässt ein Control mehrere Spalten belegen.</td></tr><tr><td>`SetRowSpan()`</td><td>Lässt ein Control mehrere Zeilen belegen.</td></tr></tbody></table>

<details id="bkmrk-getcontrolfrompositi"><summary>GetControlFromPosition()</summary>

### **GetControlFromPosition()**

```powershell
$table.GetControlFromPosition(1,0)

```

**Beschreibung:**

Liefert das Control zurück, das sich in der angegebenen Spalte und Zeile befindet.

**Rückgabe**

Rückgabetyp `System.Windows.Forms.Control`

</details><details id="bkmrk-getpositionfromcontr"><summary>GetPositionFromControl()</summary>

### **GetPositionFromControl()**

```powershell
$table.GetPositionFromControl($button)
```

**Beschreibung:**

Ermittelt die aktuelle Position eines Controls innerhalb des Rasters.

**Rückgabe:**

Rückgabetyp `System.Windows.Forms.TableLayoutPanelCellPosition`

</details><details id="bkmrk-setcolumn%28%29-setcolum"><summary>SetColumn()</summary>

### **SetColumn()**

```powershell
$table.SetColumn($button,2)
```

Verschiebt ein Control in eine andere Spalte.

</details><details id="bkmrk-setrow%28%29-setrow%28%29-%24t"><summary>SetRow()</summary>

### **SetRow()**

```powershell
$table.SetRow($button,1)
```

Verschiebt ein Control in eine andere Zeile.

</details><details id="bkmrk-setcolumnspan%28%29-setc"><summary>SetColumnSpan()</summary>

### **SetColumnSpan()**

```powershell
$table.SetColumnSpan($button,2)
```

Das Control erstreckt sich über mehrere Spalten.

</details><details id="bkmrk-setrowspan%28%29-setrows"><summary>SetRowSpan()</summary>

### **SetRowSpan()**

```powershell
$table.SetRowSpan($button,3)
```

Das Control erstreckt sich über mehrere Zeilen.

</details>### RowStyles

<details id="bkmrk-insert-insert-%24sizet"><summary>Insert</summary>

#### **Insert()**

```powershell
$sizeType = [System.Windows.Forms.SizeType]::Absolute

$rowStyle = [System.Windows.Forms.RowStyle]::new( $sizeType, 50 )

$table.RowStyles.Insert(0, $rowStyle )
```

Die Methode `Insert()` fügt an der angegebenen Position einen neuen `RowStyle` in die `RowStyles`-Sammlung ein.

Alle vorhandenen Einträge ab diesem Index werden dabei um eine Position nach hinten verschoben. Dadurch kann die Reihenfolge der Zeilenstile geändert oder zwischen bestehenden Zeilen ein neuer Stil eingefügt werden.

Die Methode verändert lediglich die `RowStyles`-Sammlung. Damit der neue Eintrag einer Zeile zugeordnet werden kann, sollte die Anzahl der Einträge in der Regel mit `RowCount` übereinstimmen.

<p class="callout warning">Die Methode `Insert()` erhöht **nicht** automatisch den Wert der Eigenschaft `RowCount`. Sie fügt lediglich einen neuen `RowStyle` in die `RowStyles`-Sammlung ein. Soll der eingefügte `RowStyle` einer zusätzlichen Zeile zugeordnet werden, muss `RowCount` entsprechend erhöht werden.</p>

**Rückgabe:**

Kein Rückgabewert.

Rückgabetyp `System.Void`

**Beispiel:**

```powershell
$table.RowCount = 3

$firstSizeType = [System.Windows.Forms.SizeType]::Absolute
$firstRowStyle = [System.Windows.Forms.RowStyle]::new( $firstSizeType, 40 )
$table.RowStyles.Add( $firstRowStyle )

$secondSizeType = [System.Windows.Forms.SizeType]::Percent
$secondRowStyle = [System.Windows.Forms.RowStyle]::new( $secondSizeType, 100 )
$table.RowStyles.Add( $secondRowStyle )

# Neuen RowStyle an Position 1 einfügen
$thirdSizeType = [System.Windows.Forms.SizeType]::Absolute
$thirdRowStyle = [System.Windows.Forms.RowStyle]::new( $thirdSizeType, 20 )
$table.RowStyles.Insert( 1, $thirdRowStyle )
```

Der neue `RowStyle` wird an Index `1` eingefügt. Der ursprünglich zweite Eintrag verschiebt sich automatisch an die nächste Position.

</details>---

## **Events**

<table id="bkmrk-event-beschreibung-l"><thead><tr><th>Event</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`Layout`</td><td>Wird ausgelöst, wenn das Layout neu berechnet wird.</td></tr><tr><td>`ControlAdded`</td><td>Ein Control wurde hinzugefügt.</td></tr><tr><td>`ControlRemoved`</td><td>Ein Control wurde entfernt.</td></tr></tbody></table>

---

<details id="bkmrk-layout-layout-das-ev"><summary>Layout</summary>

### **Layout**

Das Event wird ausgelöst, wenn das TableLayoutPanel seine Controls neu anordnet.

Dies geschieht beispielsweise bei

- Größenänderungen
- Änderungen an `ColumnStyles`
- Änderungen an `RowStyles`
- Hinzufügen oder Entfernen von Controls

```powershell
$table.Add_Layout({
    Write-Host "Layout aktualisiert"
})

```

</details><details id="bkmrk-controladded-control"><summary>ControlAdded</summary>

### **ControlAdded**

```powershell
$table.Add_ControlAdded({
    param($sender,$e)

    Write-Host $e.Control.Name
})
```

Wird ausgelöst, sobald ein Control hinzugefügt wird.

</details><details id="bkmrk-controlremoved-contr"><summary>ControlRemoved</summary>

### **ControlRemoved**

```powershell
$table.Add_ControlRemoved({
    param($sender,$e)

    Write-Host $e.Control.Name
})
```

Wird ausgelöst, sobald ein Control entfernt wird.

</details>---

## **Tipps &amp; Tricks**

##### Controls direkt einer Zelle hinzufügen

```powershell
$table.Controls.Add($button,0,1)
```

Dadurch entfällt ein späterer Aufruf von `SetColumn()` und `SetRow()`.

---

##### Control über mehrere Spalten strecken

```powershell
$table.SetColumnSpan($textBox,2)
```

Dies wird häufig für Überschriften oder TextBoxen verwendet.

---

##### Gesamten verfügbaren Platz ausfüllen

```powershell
$table.Dock = "Fill"
```

Das `TableLayoutPanel` wächst und schrumpft automatisch mit seinem Parent-Container.

---

##### Gleichmäßige Spalten erzeugen

```powershell
$table.ColumnCount = 2

$table.ColumnStyles.Add(
    [System.Windows.Forms.ColumnStyle]::new("Percent",50)
)

$table.ColumnStyles.Add(
    [System.Windows.Forms.ColumnStyle]::new("Percent",50)
)
```

Beide Spalten belegen dadurch jeweils die Hälfte der verfügbaren Breite

# Form

# Form

Ein `Form` ist das **Fenster einer Windows-Forms-Anwendung**. Es dient als oberster Container für Controls wie `Panel`, `Button`, `Label`, `TextBox`, `TabControl` oder `TableLayoutPanel`.

Ein `Form` kann sowohl als **Hauptfenster einer Anwendung** als auch als **Dialogfenster** verwendet werden.

---

## Grundlagen

Ein `Form` stellt die sichtbare Oberfläche einer Windows-Forms-Anwendung dar.

Typischer Aufbau:

```text
Form
├── Panel
│   ├── Label
│   └── Button
├── TabControl
│   ├── TabPage
│   └── TabPage
└── TableLayoutPanel
```

Controls werden über die `Controls`-Collection des Formulars hinzugefügt:

```powershell
$form.Controls.Add($button)
```

Das entspricht dem grundlegenden Aufbau der anderen Windows-Forms-Controls, die ebenfalls über eine `Controls`-Collection miteinander verschachtelt werden. 

---

## Form erstellen

### Klassisch

```powershell
$form = New-Object System.Windows.Forms.Form
```

### .NET-Style

```powershell
$form = [System.Windows.Forms.Form]::new()
```

Anschließend können Eigenschaften gesetzt und Controls hinzugefügt werden:

```powershell
$form = [System.Windows.Forms.Form]::new()

$form.Text = "Meine Anwendung"
$form.Size = "800, 600"

$button = [System.Windows.Forms.Button]::new()
$button.Text = "OK"

$form.Controls.Add($button)
```

---

## Formular anzeigen

### Nicht modal

Mit `Show()` wird das Formular angezeigt, ohne den aufrufenden Code zu blockieren.

```powershell
$form.Show()
```

Das Formular bleibt geöffnet, während das PowerShell-Skript weiter ausgeführt wird.

### Modal

Mit `ShowDialog()` wird das Formular als modales Fenster geöffnet.

```powershell
$result = $form.ShowDialog()
```

Der aufrufende Code wartet, bis das Formular geschlossen wird.

Besonders bei Dialogfenstern ist `ShowDialog()` interessant, da über `DialogResult` ein Ergebnis zurückgegeben werden kann. Dieses Prinzip wird beispielsweise auch bei Buttons verwendet. 

---

# Eigenschaften

| Eigenschaft       | Standardwert                 | Beschreibung                                                               |
| ----------------- | ---------------------------- | -------------------------------------------------------------------------- |
| `AcceptButton`    | `$null`                      | Legt den Button fest, der bei Betätigung der Enter-Taste ausgelöst wird.   |
| `AutoScaleMode`   | `Font`                       | Bestimmt, anhand welcher Grundlage das Formular automatisch skaliert wird. |
| `AutoScroll`      | `False`                      | Aktiviert automatische Scrollleisten für übergroße Inhalte.                |
| `BackColor`       | `Control`                    | Legt die Hintergrundfarbe des Formulars fest.                              |
| `BackgroundImage` | `$null`                      | Legt ein Hintergrundbild fest.                                             |
| `CancelButton`    | `$null`                      | Legt den Button fest, der bei Betätigung der Escape-Taste ausgelöst wird.  |
| `ClientSize`      | abhängig vom Standard-Layout | Legt die Größe des nutzbaren Inhaltsbereichs fest.                         |
| `ControlBox`      | `True`                       | Bestimmt, ob die Schaltflächen der Titelleiste angezeigt werden.           |
| `Cursor`          | `Default`                    | Legt den Mauszeiger innerhalb des Formulars fest.                          |
| `FormBorderStyle` | `Sizable`                    | Bestimmt die Art des Fensterrahmens.                                       |
| `Icon`            | Standardicon                 | Legt das Symbol des Fensters fest.                                         |
| `KeyPreview`      | `False`                      | Bestimmt, ob das Formular Tastatureingaben vor seinen Controls erhält.     |
| `Location`        | abhängig vom System          | Bestimmt die Position des Fensters auf dem Bildschirm.                     |
| `MaximizeBox`     | `True`                       | Legt fest, ob das Fenster maximiert werden kann.                           |
| `MaximumSize`     | `(0,0)`                      | Definiert die maximal zulässige Fenstergröße.                              |
| `MinimizeBox`     | `True`                       | Legt fest, ob das Fenster minimiert werden kann.                           |
| `MinimumSize`     | `(0,0)`                      | Definiert die minimal zulässige Fenstergröße.                              |
| `Name`            | `""`                         | Legt den internen Namen des Formulars fest.                                |
| `Opacity`         | `1.0`                        | Bestimmt die Transparenz des Fensters.                                     |
| `Padding`         | `0,0,0,0`                    | Legt den Innenabstand zwischen Fensterrahmen und Inhalt fest.              |
| `ShowIcon`        | `True`                       | Bestimmt, ob das Fenstersymbol angezeigt wird.                             |
| `ShowInTaskbar`   | `True`                       | Bestimmt, ob das Fenster in der Taskleiste erscheint.                      |
| `Size`            | abhängig vom System          | Bestimmt Breite und Höhe des Fensters.                                     |
| `StartPosition`   | `WindowsDefaultLocation`     | Bestimmt die Position beim ersten Anzeigen des Fensters.                   |
| `Text`            | `""`                         | Legt den Text in der Titelleiste fest.                                     |
| `TopMost`         | `False`                      | Legt fest, ob das Fenster immer über anderen Fenstern bleibt.              |
| `WindowState`     | `Normal`                     | Bestimmt den aktuellen Zustand des Fensters.                               |

---

<details>
<summary>AcceptButton</summary>

### **AcceptButton**

**Typ** = `[System.Windows.Forms.IButtonControl]`

`AcceptButton` legt fest, welcher Button ausgelöst wird, wenn der Benutzer innerhalb des Formulars die **Enter-Taste** betätigt.

```powershell
$form.AcceptButton = $okButton
```

Dies ist besonders bei Dialogfenstern praktisch:

```powershell
$okButton = [System.Windows.Forms.Button]::new()
$okButton.Text = "OK"

$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
```

Der Benutzer kann dadurch beispielsweise ein Formular mit Enter bestätigen, ohne den Button mit der Maus anzuklicken.

</details>

---

<details>
<summary>AutoScaleMode</summary>

### **AutoScaleMode**

**Typ** = `[System.Windows.Forms.AutoScaleMode]`

`AutoScaleMode` bestimmt, anhand welcher Grundlage das Formular und seine Controls automatisch skaliert werden.

Typische Werte sind:

* `None` → keine automatische Skalierung
* `Font` → Skalierung anhand der Schriftgröße
* `Dpi` → Skalierung anhand der DPI-Einstellung
* `Inherit` → übernimmt die Einstellung des übergeordneten Controls

```powershell
$form.AutoScaleMode = "Font"
```

Gerade bei unterschiedlichen Windows-Skalierungseinstellungen kann diese Eigenschaft wichtig sein, damit die Oberfläche nicht plötzlich aussieht, als hätte Windows sie durch einen Briefkastenschlitz geschoben.

</details>

---

<details>
<summary>AutoScroll</summary>

### **AutoScroll**

**Typ** = `[System.Boolean]`

`AutoScroll` aktiviert automatische Scrollleisten, wenn der Inhalt des Formulars größer als dessen sichtbarer Bereich ist.

**Standardwert** = `False`

```powershell
$form.AutoScroll = $true
```

Die Eigenschaft ist besonders bei Formularen mit dynamisch erzeugten oder umfangreichen Controls hilfreich.

</details>

---

<details>
<summary>BackColor</summary>

### **BackColor**

**Typ** = `[System.Drawing.Color]`

`BackColor` legt die Hintergrundfarbe des Formulars fest.

```powershell
$form.BackColor = "White"
```

</details>

---

<details>
<summary>BackgroundImage</summary>

### **BackgroundImage**

**Typ** = `[System.Drawing.Image]`

`BackgroundImage` legt ein Bild fest, das als Hintergrund des Formulars dargestellt wird.

```powershell
$form.BackgroundImage = [System.Drawing.Image]::FromFile(
    "C:\Images\background.png"
)
```

Die Darstellung des Bildes kann zusätzlich über `BackgroundImageLayout` beeinflusst werden.

</details>

---

<details>
<summary>CancelButton</summary>

### **CancelButton**

**Typ** = `[System.Windows.Forms.IButtonControl]`

`CancelButton` legt fest, welcher Button ausgelöst wird, wenn der Benutzer die **Escape-Taste** betätigt.

```powershell
$form.CancelButton = $cancelButton
```

Typischerweise wird hier ein Abbrechen-Button hinterlegt.

```powershell
$cancelButton.DialogResult = "Cancel"

$form.CancelButton = $cancelButton
```

Bei einem Dialogfenster kann dadurch die Escape-Taste zum Abbrechen verwendet werden.

</details>

---

<details>
<summary>ClientSize</summary>

### **ClientSize**

**Typ** = `[System.Drawing.Size]`

`ClientSize` bestimmt die Größe des **nutzbaren Inhaltsbereichs** des Formulars.

Im Gegensatz zu `Size` berücksichtigt `ClientSize` nicht den Fensterrahmen und die Titelleiste.

```powershell
$form.ClientSize = "800, 500"
```

Das ist insbesondere bei Layoutberechnungen interessant, wenn die Größe des eigentlichen Inhaltsbereichs relevant ist.

In deinem Windows-Setup-Helper verwendest du beispielsweise `ClientSize`, um die Formulargröße abhängig von der ausgewählten `TabPage` anzupassen. 

</details>

---

<details>
<summary>ControlBox</summary>

### **ControlBox**

**Typ** = `[System.Boolean]`

`ControlBox` bestimmt, ob die Steuerelemente der Titelleiste angezeigt werden.

**Standardwert** = `True`

```powershell
$form.ControlBox = $false
```

Bei deaktivierter `ControlBox` werden die entsprechenden Fenster-Schaltflächen wie Schließen, Minimieren und Maximieren nicht mehr auf normale Weise dargestellt.

</details>

---

<details>
<summary>FormBorderStyle</summary>

### **FormBorderStyle**

**Typ** = `[System.Windows.Forms.FormBorderStyle]`

`FormBorderStyle` bestimmt die Art des Fensterrahmens und damit unter anderem, ob der Benutzer die Größe des Fensters verändern kann.

Typische Werte:

| Wert                | Beschreibung                       |
| ------------------- | ---------------------------------- |
| `None`              | Kein Fensterrahmen                 |
| `FixedSingle`       | Fester einfacher Rahmen            |
| `Fixed3D`           | Fester 3D-Rahmen                   |
| `FixedDialog`       | Fester Dialograhmen                |
| `Sizable`           | Fenstergröße kann verändert werden |
| `FixedToolWindow`   | Festes Werkzeugfenster             |
| `SizableToolWindow` | Veränderbares Werkzeugfenster      |

```powershell
$form.FormBorderStyle = "FixedDialog"
```

Für normale Hauptfenster ist `Sizable` üblich.

</details>

---

<details>
<summary>Icon</summary>

### **Icon**

**Typ** = `[System.Drawing.Icon]`

`Icon` legt das Symbol des Formulars fest.

```powershell
$form.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon(
    "C:\Program Files\App\App.exe"
)
```

Das Icon kann unter anderem in der Titelleiste und Taskleiste angezeigt werden.

</details>

---

<details>
<summary>KeyPreview</summary>

### **KeyPreview**

**Typ** = `[System.Boolean]`

`KeyPreview` bestimmt, ob das Formular Tastatureingaben **vor den enthaltenen Controls** erhält.

**Standardwert** = `False`

```powershell
$form.KeyPreview = $true
```

Dadurch können beispielsweise globale Tastenkombinationen auf Formularebene behandelt werden.

```powershell
$form.Add_KeyDown({
    param($sender, $e)

    if ($e.KeyCode -eq "F5") {
        Write-Host "F5 gedrückt"
    }
})
```

Ohne `KeyPreview` kann ein fokussiertes Control die Tastatureingabe zuerst verarbeiten.

</details>

---

<details>
<summary>Location</summary>

### **Location**

**Typ** = `[System.Drawing.Point]`

`Location` legt die Position des Formulars auf dem Bildschirm fest.

```powershell
$form.Location = "100, 100"
```

Die beiden Werte entsprechen:

```text
X = 100
Y = 100
```

Die Startposition kann alternativ über `StartPosition` automatisch bestimmt werden.

</details>

---

<details>
<summary>MaximizeBox</summary>

### **MaximizeBox**

**Typ** = `[System.Boolean]`

`MaximizeBox` bestimmt, ob das Fenster über die Titelleiste maximiert werden kann.

**Standardwert** = `True`

```powershell
$form.MaximizeBox = $false
```

Bei Dialogfenstern wird die Maximierung häufig deaktiviert.

</details>

---

<details>
<summary>MaximumSize</summary>

### **MaximumSize**

**Typ** = `[System.Drawing.Size]`

`MaximumSize` legt die maximal zulässige Größe des Formulars fest.

**Standardwert** = `(0,0)`

Der Wert `(0,0)` bedeutet, dass keine maximale Größe festgelegt wurde.

```powershell
$form.MaximumSize = "1200, 800"
```

</details>

---

<details>
<summary>MinimizeBox</summary>

### **MinimizeBox**

**Typ** = `[System.Boolean]`

`MinimizeBox` bestimmt, ob das Fenster über die Titelleiste minimiert werden kann.

**Standardwert** = `True`

```powershell
$form.MinimizeBox = $false
```

</details>

---

<details>
<summary>MinimumSize</summary>

### **MinimumSize**

**Typ** = `[System.Drawing.Size]`

`MinimumSize` legt die minimal zulässige Größe des Formulars fest.

**Standardwert** = `(0,0)`

```powershell
$form.MinimumSize = "600, 400"
```

Damit kann verhindert werden, dass der Benutzer das Fenster so weit verkleinert, dass Controls nicht mehr sinnvoll dargestellt werden.

</details>

---

<details>
<summary>Name</summary>

### **Name**

**Typ** = `[System.String]`

`Name` legt den internen Namen des Formulars fest.

```powershell
$form.Name = "MainForm"
```

Der Name dient der Identifikation innerhalb des Programms und wird dem Benutzer nicht angezeigt.

</details>

---

<details>
<summary>Opacity</summary>

### **Opacity**

**Typ** = `[System.Double]`

`Opacity` bestimmt die Deckkraft des Fensters.

Der Wertebereich liegt zwischen `0` und `1`.

|  Wert | Darstellung             |
| ----: | ----------------------- |
|   `0` | vollständig transparent |
| `0.5` | 50 % Deckkraft          |
|   `1` | vollständig sichtbar    |

```powershell
$form.Opacity = 0.8
```

**Standardwert** = `1`

</details>

---

<details>
<summary>Padding</summary>

### **Padding**

**Typ** = `[System.Windows.Forms.Padding]`

`Padding` legt den Innenabstand zwischen dem Rand des Formulars und dessen Inhalt fest.

```powershell
$form.Padding = [System.Windows.Forms.Padding]::new(10)
```

Der Wert wird insbesondere beim Layout der enthaltenen Controls berücksichtigt.

</details>

---

<details>
<summary>ShowIcon</summary>

### **ShowIcon**

**Typ** = `[System.Boolean]`

`ShowIcon` bestimmt, ob das Icon des Formulars in der Titelleiste angezeigt wird.

**Standardwert** = `True`

```powershell
$form.ShowIcon = $false
```

</details>

---

<details>
<summary>ShowInTaskbar</summary>

### **ShowInTaskbar**

**Typ** = `[System.Boolean]`

`ShowInTaskbar` bestimmt, ob das Formular als eigenes Fenster in der Windows-Taskleiste erscheint.

**Standardwert** = `True`

```powershell
$form.ShowInTaskbar = $false
```

Dies kann beispielsweise bei Hilfs- oder Dialogfenstern sinnvoll sein.

</details>

---

<details>
<summary>Size</summary>

### **Size**

**Typ** = `[System.Drawing.Size]`

`Size` bestimmt die gesamte Größe des Formulars einschließlich Fensterrahmen und Titelleiste.

```powershell
$form.Size = "800, 600"
```

Für die Größe des reinen Inhaltsbereichs sollte stattdessen `ClientSize` verwendet werden.

</details>

---

<details>
<summary>StartPosition</summary>

### **StartPosition**

**Typ** = `[System.Windows.Forms.FormStartPosition]`

`StartPosition` bestimmt, wo das Formular beim ersten Anzeigen positioniert wird.

Typische Werte:

| Wert                     | Beschreibung                                 |
| ------------------------ | -------------------------------------------- |
| `Manual`                 | Position wird über `Location` bestimmt       |
| `CenterScreen`           | Zentriert auf dem Bildschirm                 |
| `WindowsDefaultLocation` | Windows bestimmt die Position                |
| `WindowsDefaultBounds`   | Windows bestimmt Position und Größe          |
| `CenterParent`           | Zentriert relativ zum übergeordneten Fenster |

Beispiel:

```powershell
$form.StartPosition = "CenterScreen"
```

Für Dialogfenster ist häufig `CenterParent` sinnvoll.

</details>

---

<details>
<summary>Text</summary>

### **Text**

**Typ** = `[System.String]`

`Text` bestimmt den Text in der Titelleiste des Formulars.

**Standardwert** = `""`

```powershell
$form.Text = "Meine Anwendung"
```

In deinem Windows-Setup-Helper wird der Titel beispielsweise beim `Load`-Event dynamisch erweitert. 

</details>

---

<details>
<summary>TopMost</summary>

### **TopMost**

**Typ** = `[System.Boolean]`

`TopMost` bestimmt, ob das Formular dauerhaft über anderen normalen Fenstern angezeigt wird.

**Standardwert** = `False`

```powershell
$form.TopMost = $true
```

Ein `TopMost`-Fenster bleibt über normalen Fenstern, auch wenn diese den Fokus erhalten.

</details>

---

<details>
<summary>WindowState</summary>

### **WindowState**

**Typ** = `[System.Windows.Forms.FormWindowState]`

`WindowState` bestimmt den aktuellen Zustand des Formulars.

Mögliche Werte:

| Wert        | Beschreibung               |
| ----------- | -------------------------- |
| `Normal`    | Normale Fensterdarstellung |
| `Minimized` | Minimiert                  |
| `Maximized` | Maximiert                  |

```powershell
$form.WindowState = "Maximized"
```

Der Standardwert ist:

```text
Normal
```

</details>

---

# Methoden

| Methode            | Beschreibung                                                 |
| ------------------ | ------------------------------------------------------------ |
| `Show()`           | Zeigt das Formular nicht modal an.                           |
| `ShowDialog()`     | Zeigt das Formular modal an und wartet auf dessen Schließen. |
| `Close()`          | Schließt das Formular.                                       |
| `Hide()`           | Versteckt das Formular, ohne es zu schließen.                |
| `Activate()`       | Aktiviert das Formular und bringt es in den Vordergrund.     |
| `CenterToScreen()` | Zentriert das Formular auf dem Bildschirm.                   |
| `CenterToParent()` | Zentriert das Formular relativ zum Parent-Fenster.           |
| `Refresh()`        | Erzwingt eine Aktualisierung der Darstellung.                |
| `Focus()`          | Versucht, den Tastaturfokus auf das Formular zu setzen.      |
| `Dispose()`        | Gibt die vom Formular verwendeten Ressourcen frei.           |

---

<details>
<summary>Show()</summary>

### **Show()**

```powershell
$form.Show()
```

Zeigt das Formular an, ohne den aufrufenden Code zu blockieren.

Das Skript kann nach dem Aufruf weiterarbeiten.

</details>

---

<details>
<summary>ShowDialog()</summary>

### **ShowDialog()**

```powershell
$result = $form.ShowDialog()
```

Zeigt das Formular als **modales Fenster** an.

Der aufrufende Code wird angehalten, bis das Formular geschlossen wird.

Der Rückgabewert ist ein `[System.Windows.Forms.DialogResult]`.

```powershell
$result = $form.ShowDialog()

if ($result -eq "OK") {
    Write-Host "Bestätigt"
}
```

Zusammen mit `AcceptButton`, `CancelButton` und `DialogResult` lassen sich damit klassische Dialogfenster aufbauen.

</details>

---

<details>
<summary>Close()</summary>

### **Close()**

```powershell
$form.Close()
```

Schließt das Formular.

Bei einem Hauptformular kann das Schließen außerdem dazu führen, dass die Anwendung beendet wird, abhängig davon, wie die Windows-Forms-Anwendung gestartet wurde.

</details>

---

<details>
<summary>Hide()</summary>

### **Hide()**

```powershell
$form.Hide()
```

Versteckt das Formular, ohne es zu zerstören.

Das Formular kann anschließend erneut mit `Show()` angezeigt werden.

```powershell
$form.Hide()

# später
$form.Show()
```

Im Gegensatz zu `Close()` bleibt das Formular dabei bestehen.

</details>

---

<details>
<summary>Activate()</summary>

### **Activate()**

```powershell
$form.Activate()
```

Aktiviert das Formular und versucht, es in den Vordergrund zu bringen.

Dies kann beispielsweise verwendet werden, wenn ein bereits geöffnetes Fenster erneut angezeigt werden soll.

</details>

---

<details>
<summary>CenterToScreen()</summary>

### **CenterToScreen()**

```powershell
$form.CenterToScreen()
```

Positioniert das Formular in der Mitte des Bildschirms.

Alternativ kann bereits beim Start festgelegt werden:

```powershell
$form.StartPosition = "CenterScreen"
```

</details>

---

<details>
<summary>CenterToParent()</summary>

### **CenterToParent()**

```powershell
$form.CenterToParent()
```

Zentriert das Formular relativ zu seinem übergeordneten Fenster.

Dies ist insbesondere für Dialogfenster sinnvoll.

</details>

---

<details>
<summary>Dispose()</summary>

### **Dispose()**

```powershell
$form.Dispose()
```

Gibt die vom Formular verwendeten Ressourcen frei.

Nach `Dispose()` sollte das Formular nicht weiterverwendet werden.

In deinem Setup-Helper wird beispielsweise das aktuelle Formular über `Dispose()` geschlossen und freigegeben, bevor der Prozess anschließend neu gestartet wird. 

</details>

---

# Events

Ein `Form` besitzt eine große Anzahl an Events. Besonders häufig werden folgende verwendet:

| Event         | Beschreibung                                                   |
| ------------- | -------------------------------------------------------------- |
| `Load`        | Wird ausgelöst, wenn das Formular geladen wird.                |
| `Shown`       | Wird ausgelöst, nachdem das Formular erstmals angezeigt wurde. |
| `FormClosing` | Wird unmittelbar vor dem Schließen ausgelöst.                  |
| `FormClosed`  | Wird nach dem Schließen ausgelöst.                             |
| `Resize`      | Wird bei einer Größenänderung ausgelöst.                       |
| `SizeChanged` | Wird ausgelöst, wenn sich `Size` ändert.                       |
| `KeyDown`     | Wird beim Drücken einer Taste ausgelöst.                       |
| `KeyUp`       | Wird beim Loslassen einer Taste ausgelöst.                     |
| `KeyPress`    | Wird bei einer Zeichen-Tastatureingabe ausgelöst.              |
| `Activated`   | Wird ausgelöst, wenn das Formular aktiviert wird.              |
| `Deactivate`  | Wird ausgelöst, wenn das Formular den Fokus verliert.          |
| `Move`        | Wird beim Verschieben des Formulars ausgelöst.                 |

Beispiel:

```powershell
$form.Add_Load({
    Write-Host "Formular geladen"
})

$form.Add_Shown({
    Write-Host "Formular angezeigt"
})

$form.Add_FormClosed({
    Write-Host "Formular geschlossen"
})
```

In deinem eigenen Code verwendest du beispielsweise `FormClosed`, `Load`, `Resize` und `Shown` für unterschiedliche Initialisierungs- und Lebenszyklusaufgaben. 

---

## Typischer Aufbau

Ein einfaches Formular mit Button kann beispielsweise so aussehen:

```powershell
Add-Type -AssemblyName System.Windows.Forms

$form = [System.Windows.Forms.Form]::new()
$form.Text = "Meine Anwendung"
$form.ClientSize = "500, 300"
$form.StartPosition = "CenterScreen"

$button = [System.Windows.Forms.Button]::new()
$button.Text = "Schließen"
$button.Size = "120, 35"
$button.Location = "190, 130"

$button.Add_Click({
    $form.Close()
})

$form.Controls.Add($button)

$form.ShowDialog()
```

Damit entsteht bereits eine vollständige kleine Windows-Forms-Anwendung:

```text
┌─────────────────────────────────────┐
│ Meine Anwendung                 □ × │
├─────────────────────────────────────┤
│                                     │
│             ┌──────────┐            │
│             │ Schließen│            │
│             └──────────┘            │
│                                     │
└─────────────────────────────────────┘
```

---

## `Size` vs. `ClientSize`

Bei `Form` ist die Unterscheidung besonders wichtig:

```powershell
$form.Size = "800, 600"
```

bestimmt die **gesamte Fenstergröße**.

```powershell
$form.ClientSize = "800, 600"
```

bestimmt dagegen die Größe des **nutzbaren Bereichs innerhalb des Fensterrahmens**.

Das ist einer dieser kleinen .NET-Unterschiede, die zunächst völlig harmlos aussehen und später dafür sorgen, dass ein Layout um exakt die Höhe der Titelleiste danebenliegt.

---

## `Show()` vs. `ShowDialog()`

| Methode        | Modal | Blockiert Code | Rückgabewert   |
| -------------- | ----: | -------------: | -------------- |
| `Show()`       |     ❌ |              ❌ | keiner         |
| `ShowDialog()` |     ✅ |              ✅ | `DialogResult` |

Für ein normales Hauptfenster:

```powershell
$form.Show()
```

Für einen Dialog:

```powershell
$result = $form.ShowDialog()
```

---

# Hinweise

* `Form` ist selbst ein `Control` und kann deshalb viele Eigenschaften und Events der Basisklasse verwenden.
* Ein Formular besitzt eine `Controls`-Collection und kann damit als Container für andere Controls dienen.
* `Show()` eignet sich für nicht-modale Fenster.
* `ShowDialog()` eignet sich für modale Dialogfenster.
* `Close()` schließt das Formular, während `Hide()` es lediglich unsichtbar macht.
* `Dispose()` gibt die verwendeten Ressourcen frei.
* `ClientSize` beschreibt den nutzbaren Inhaltsbereich, `Size` dagegen die gesamte Fenstergröße.
* `StartPosition` ist für die Positionierung beim ersten Anzeigen zuständig.
* `KeyPreview` ist nützlich, wenn das Formular Tastatureingaben unabhängig vom fokussierten Control verarbeiten soll.
* `AcceptButton` und `CancelButton` erleichtern die Umsetzung klassischer Dialogfenster.

Damit ist `Form` im Grunde die oberste Ebene deiner gesamten WinForms-Struktur. `Panel`, `TableLayoutPanel`, `TabControl` und Co. organisieren den Inhalt darin, während `Form` das eigentliche Fenster und dessen Lebenszyklus verwaltet. Das passt auch ziemlich genau zu dem Aufbau, den du in deinen eigenen PowerShell-UI-Strukturen bereits verwendest.