public/New-Window.ps1

using namespace System.Windows.Markup
using namespace System.Windows.Controls
using namespace System.Windows.Media

Add-Type -AssemblyName PresentationFramework

<#
.SYNOPSIS
Creates a new WPF window with a specified title, height, width, and content.

.DESCRIPTION
This function creates a new WPF window with a specified title, height, width, and content.
The content is provided as an array of controls created using the New-Control function.
The window includes a cancel and submit button with configurable text, validates required fields
and pattern constraints before accepting input, and returns the dialog result and content when closed.
The content is displayed in a scrollable area, and the window can be resized.

.PARAMETER Title
The title of the window. Default is 'User Interface'.

.PARAMETER Height
The height of the window in pixels. Must be between 100 and 2000. Default is 700.

.PARAMETER Width
The width of the window in pixels. Must be between 100 and 2000. Default is 450.

.PARAMETER Content
An array of controls to be displayed in the window. The controls are created using the New-Control function.

.PARAMETER SubmitButtonText
The text displayed on the submit button. Default is 'Submit'.

.PARAMETER CancelButtonText
The text displayed on the cancel button. Default is 'Cancel'.

.EXAMPLE
$Content = @'
ControlType; Name; Value
Headline;Headline ONE;
TextBox;Label-Text 11
TextBox;Label-Text 12;Default-Value 12
ComboBox;ComboBox Label 24;Wert A,Wert B,Wert C
Headline;Headline TWO;
CheckBox;Label-Text 21
CheckBox;Label-Text 22;True
'@ | ConvertFrom-Csv -Delimiter ';' | New-Control
New-Window -Title 'Test Window' -Height 400 -Width 600 -Content $Content -Verbose

.EXAMPLE
# Window with custom button text and validation
$Content = @'
ControlType;Name;Value;Required
Headline;Neuer Mitarbeiter
TextBox;Vorname;;True
TextBox;E-Mail;;True
ComboBox;Abteilung;Entwicklung,Marketing,Vertrieb;
DatePicker;Startdatum;;True
'@ | ConvertFrom-Csv -Delimiter ';' | New-Control
$Result = New-Window -Title 'Erfassung' -Content $Content -SubmitButtonText 'Speichern' -CancelButtonText 'Abbrechen' -Height 300
#>


function New-Window {
    [CmdletBinding()]
    param (
        [string]$Title = 'User Interface',
        
        [ValidateRange(100, 2000)]
        [int]$Height = 700,
        
        [ValidateRange(100, 2000)]
        [int]$Width = 450,

        [Parameter(Mandatory, ValueFromPipeline)]
        [ValidateCount(1, 100)]
        [Grid[]]$Content,

        [string]$SubmitButtonText = 'Submit',

        [string]$CancelButtonText = 'Cancel'
    )

    begin {
        $WindowXaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        WindowStartupLocation="CenterScreen" ResizeMode="CanResizeWithGrip">
    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="AUTO"/>
            </Grid.RowDefinitions>

            <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
                <WrapPanel x:Name="ContentWrapPanel" Orientation="Vertical" />
            </ScrollViewer>

            <Grid Grid.Row="1" Margin="5">
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                    <Button x:Name="CancelButton" Padding="20 5 20 5" Margin="10" IsCancel="True" />
                    <Button x:Name="SubmitButton" Padding="20 5 20 5" Margin="10" IsDefault="True" />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</Window>
"@

        try {
            $Window = [XamlReader]::Parse($WindowXaml)
        }
        catch {
            $PSCmdlet.ThrowTerminatingError(
                [System.Management.Automation.ErrorRecord]::new(
                    [System.InvalidOperationException]::new(
                        "Fehler beim Erstellen des Fensters: $($_.Exception.Message)",
                        $_.Exception
                    ),
                    'WindowCreationFailed',
                    [System.Management.Automation.ErrorCategory]::InvalidOperation,
                    $null
                )
            )
        }

        $Window.Title = $Title
        $Window.Height = $Height
        $Window.Width = $Width
        
        $ContentWrapPanel = $Window.FindName('ContentWrapPanel')
        
        $CancelButton = $Window.FindName('CancelButton')
        $CancelButton.Content = $CancelButtonText

        $SubmitButton = $Window.FindName('SubmitButton')
        $SubmitButton.Content = $SubmitButtonText
        $SubmitButton.Add_Click({
            $HasErrors = $false

            foreach ($child in $ContentWrapPanel.Children) {
                $ValueControl = $child.FindName('ValueControl')
                if ($null -eq $ValueControl) { continue }

                # Reset visual feedback
                if ($ValueControl -is [Control]) {
                    $ValueControl.ClearValue([Control]::BorderBrushProperty)
                    $ValueControl.ToolTip = $null
                }

                $Tag = $child.Tag
                if ($null -eq $Tag) { continue }

                # Get current value for validation
                $CurrentValue = switch ($ValueControl) {
                    { $_ -is [TextBox] }     { $_.Text }
                    { $_ -is [PasswordBox] } { $_.Password }
                    { $_ -is [ComboBox] }    { $_.SelectedValue }
                    { $_ -is [DatePicker] }  { $_.SelectedDate }
                    default { $null }
                }

                # Required validation
                if ($Tag.Required) {
                    $IsEmpty = ($null -eq $CurrentValue) -or ([string]::IsNullOrWhiteSpace("$CurrentValue"))

                    if ($IsEmpty) {
                        $HasErrors = $true
                        if ($ValueControl -is [Control]) {
                            $ValueControl.BorderBrush = [Brushes]::Red
                            $ValueControl.ToolTip = 'Pflichtfeld'
                        }
                        continue
                    }
                }

                # Pattern validation (text-based controls only)
                if ($Tag.ValidationPattern -and $CurrentValue -is [string] -and -not [string]::IsNullOrEmpty($CurrentValue)) {
                    if ($CurrentValue -notmatch $Tag.ValidationPattern) {
                        $HasErrors = $true
                        if ($ValueControl -is [Control]) {
                            $ValueControl.BorderBrush = [Brushes]::Red
                            $ValueControl.ToolTip = 'Ungültiges Format'
                        }
                        continue
                    }
                }
            }

            if (-not $HasErrors) {
                $Window.DialogResult = $true
                $Window.Close()
            }
        })
    }
    
    process {
        foreach ($item in $Content) {
            $ContentWrapPanel.Children.Add($item) | Out-Null
        }
    }

    end {
        $DialogResult = $Window.ShowDialog()
        "Window Size: $($Window.ActualHeight) x $($Window.ActualWidth)" | Write-Verbose

        $Id = 1
        $ResultControlContent = [System.Collections.Generic.List[PSCustomObject]]::new()

        foreach ($item in $Content) {
            
            if ($null -ne $item.FindName('Headline')) {
                continue
            }
            
            $LabelControl = $item.FindName('LabelControl')
            $Name = $LabelControl.Content

            $ValueControl = $item.FindName('ValueControl')
            $Value = switch ($ValueControl) {
                { $_ -is [TextBox] }     { $ValueControl.Text }
                { $_ -is [CheckBox] }    { $ValueControl.IsChecked }
                { $_ -is [ComboBox] }    { $ValueControl.SelectedValue }
                { $_ -is [DatePicker] }  { $ValueControl.SelectedDate }
                { $_ -is [RadioButton] } { $ValueControl.IsChecked }
                { $_ -is [PasswordBox] } { $ValueControl.Password }
                Default { $null }
            }

            $ResultControlContent.Add([PSCustomObject]@{ Id = $Id++ ; Name = $Name ; Value = $Value })
        }

        $Result = [PSCustomObject]@{
            DialogResult = $DialogResult
            Content      = $ResultControlContent
        }
        return $Result
    }
}