约 2783 字

约 14 分钟

#WPF 图形界面

WPF(Windows Presentation Foundation)使用 XAML 描述界面,PowerShell 负责加载 XAML 并绑定事件。相比 WinForms,WPF 的布局和样式能力更强。

#加载程序集

> Add-Type -AssemblyName PresentationFramework
> Add-Type -AssemblyName PresentationCore
> Add-Type -AssemblyName WindowsBase

PresentationFramework 提供窗口、控件和 XamlReader;PresentationCore 与 WindowsBase 提供底层类型。

#XAML 与 PowerShell 结合

把界面写在 XAML 字符串中,再用 XamlReader 解析:

wpf.ps1

Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName WindowsBase

$xaml = @'
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF 示例" Height="220" Width="420"
        WindowStartupLocation="CenterScreen">
    <StackPanel Margin="20">
        <TextBlock Text="请输入姓名:" />
        <TextBox x:Name="NameBox" Margin="0,8,0,0" />
        <Button x:Name="OkButton" Content="确定"
                Width="80" Margin="0,16,0,0"
                HorizontalAlignment="Left" />
    </StackPanel>
</Window>
'@

$reader = New-Object System.Xml.XmlNodeReader ([xml]$xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
  • x:Name 为控件命名,之后可以通过 FindName 获取。
  • [xml]$xaml 把字符串解析为 XML 文档。
  • XmlNodeReader 把 XML 节点提供给 XamlReader.Load。

#获取控件与事件处理

wpf.ps1

$nameBox = $window.FindName('NameBox')
$okButton = $window.FindName('OkButton')

$okButton.Add_Click({
    $name = $nameBox.Text
    if ([string]::IsNullOrWhiteSpace($name)) {
        [System.Windows.MessageBox]::Show('请输入姓名')
        return
    }

    [System.Windows.MessageBox]::Show("你好,$name")
})

$window.ShowDialog() | Out-Null
  • FindName 按 XAML 中的 x:Name 查找控件。
  • Add_Click 注册事件脚本块,脚本块会捕获外层的 $nameBox 等变量。
  • ShowDialog() 以模态方式显示窗口。

#使用 XAML 文件

界面较长时,可以把 XAML 放在单独文件中:

wpf-file.ps1

Add-Type -AssemblyName PresentationFramework

$xamlPath = Join-Path $PSScriptRoot 'MainWindow.xaml'
$reader = New-Object System.Xml.XmlNodeReader ([xml](Get-Content -Raw $xamlPath))
$window = [Windows.Markup.XamlReader]::Load($reader)

$window.FindName('OkButton').Add_Click({
    [System.Windows.MessageBox]::Show('按钮被点击')
})

$window.ShowDialog() | Out-Null

Get-Content -Raw 一次性读取完整文本,避免逐行读取破坏 XML 结构。

#注意事项

  • WPF 仅在 Windows 上可用,跨平台脚本不应依赖它。
  • WPF 需要 STA 线程。若提示“调用线程必须为 STA”,请使用 pwsh -Sta 启动。
  • XAML 中的事件属性(如 Click="...")无法直接绑定 PowerShell 脚本块,通常通过 Add_Click 注册。
  • 界面操作应在 UI 线程执行,耗时任务需要使用后台线程或 Dispatcher。

#推荐阅读

更新: 2026/11/2

作者: planc

创建: 2026/11/2