Search code examples
wpfpowershellpopupwindow

PowerShell WPF popup window behaviour


I Have a PowerShell WPF XAML script. I Need to open popup window and then update it with text. The problem is that popup window only opens at the end of function, and for at the start, even if I specify to open popup. Is it possible to open popup window first and then update it, or is it just the behaviour or popup and can't change it?

Test Code:

# Function to get output and
function Test-Popup {
    # $output = Get-Content ".\output.txt" # Test output file
    # return $output
}
[xml]$XAML = @"
<Window Name="wpfWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Width="342"
        Height="267"
        Background="White"
        Title="WPF Window"
        Topmost="True"
        WindowStartupLocation="CenterScreen"
        WindowStyle="ToolWindow">
  <Grid Name="Main_Window" Background="White">
  <Popup Name="Loading_PopUp" Placement="Center" IsOpen="False" Width="300" Height="250">
            <Grid Background="LightGray">
                <Label Width="290" HorizontalAlignment="Center" Margin="0,10,0,0">
                    <TextBlock Name="install_info" TextWrapping="Wrap"/>
                </Label>
            </Grid>
        </Popup>
        <Button Name="Install" Content="Install" HorizontalAlignment="Left" Margin="10,10,0,10" VerticalAlignment="Top" Width="104" Height="23"/>
  </Grid>
</Window>
"@
[Void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
try {

    $XMLReader = (New-Object System.Xml.XmlNodeReader $XAML)
    $XMLForm = [Windows.Markup.XamlReader]::Load($XMLReader)
} 
catch {
    Write-Error "Error building Xaml data.`n$_"
    exit
}
$Xaml.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $XMLForm.FindName($_.Name) -Scope Script }
$install.add_Click({
    $Loading_PopUp.IsOpen = $true
    Start-Sleep 5
    $Message = Test-Popup
    $install_info.AddText($Message)
    })

$XMLForm.ShowDialog() | 
Out-Null

I know that I can use PowerShell forms, and it works as I want, I can use second XAML. But is it possible to use popup window?


Solution

  • Start-Sleep blocks the UI thread.

    You must perform the long-running action on another thread or you could use a DispatcherTimer to delay the operation that sets the text:

    $dispatcherTimer = [System.Windows.Threading.DispatcherTimer]::new()
    $dispatcherTimer.Interval = [timespan]::FromSeconds(5)
    $dispatcherTimer.Add_Tick( { 
        $Message = Test-Popup
        $install_info.AddText($Message)
    
        $timer = [System.Windows.Threading.DispatcherTimer]$args[0]
        $timer.Stop();
    } )
    
    $install.add_Click({
        $dispatcherTimer.Stop()
        $Loading_PopUp.IsOpen = $true
        $dispatcherTimer.Start()
    })