Обновление графического интерфейса WPF с использованием заданий Powershell
Я пытался создать адаптивный графический интерфейс для моих личных скриптов Powershell. У меня возникла проблема, которая широко обсуждается в Интернете: заморозка графического интерфейса (поскольку Powershell является однопоточным).
Похожа на эту проблему, но мой случай специфичен для Powershell. Я успешно реализовал решение на основе Powershell для создания графических интерфейсов, основанных на форме XAML. Теперь давайте рассмотрим этот код:
#EVENT Handler
$Somebutton.add_Click({
$SomeLabel.Content = "Calculating..."
Start-Job -ScriptBlock {
#Computation that takes time
#...
$SomeLabel.Content = "Calculated value"
}
})
#Show XAML GUI
$xamlGUI.ShowDialog() | out-null
xamlGUI
сама форма и $Somebutton
/$SomeLabel
это элементы управления, которые я смог прочитать из xaml и преобразовать в переменные Powershell.
Я пытаюсь понять, почему задание, которое я запускаю, не обновляет мой ярлык после завершения вычислений. Это на самом деле ничего не делает.
Я новичок в работе Powershell, и мне интересно, есть ли что-то, что я пропускаю.
1 ответ
Вот небольшой пример, который я использую для реактивных форм WPF в PowerShell:
# Hide yo console
$SW_HIDE, $SW_SHOW = 0, 5
$TypeDef = '[DllImport("User32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);'
Add-Type -MemberDefinition $TypeDef -Namespace Win32 -Name Functions
$hWnd = (Get-Process -Id $PID).MainWindowHandle
$Null = [Win32.Functions]::ShowWindow($hWnd,$SW_HIDE)
# Define your app + form
Add-Type -AssemblyName PresentationFramework
$App = [Windows.Application]::new() # or New-Object -TypeName Windows.Application
$Form = [Windows.Markup.XamlReader]::Load(
[Xml.XmlNodeReader]::new([xml]@'
WPF form definition goes here
'@)
)
# or ::Load((New-Object -TypeName Xml.XmlNodeReader -ArgumentList ([xml]@'
#wpfdef
#'@))
#)
# Fixes the "freeze" problem
function Update-Gui {
# Basically WinForms Application.DoEvents()
$App.Dispatcher.Invoke([Windows.Threading.DispatcherPriority]::Background, [action]{})
}
# Event handlers go here
$Form.add_Closing({
$Form.Close()
$App.Shutdown()
Stop-Process -Id $PID # or return your console: [Win32.Functions]::ShowWindow($hWnd,$SW_SHOW)
})
# Finally
$App.Run($Form)
Не забудьте очистить, когда ваше приложение закрывается:
$Form.Close()
$App.Shutdown()
Stop-Process -Id $PID
Всякий раз, когда вам нужно отразить изменения в GUI, позвоните в Update-Gui
функция.