PowerShell中XAML按钮点击动态添加Panel面板与窗口刷新实现问询
PowerShell 动态操作WPF XAML表单元素实现方案
核心需求
实现类似Android端Java动态添加XML对象的效果,在PowerShell中向XAML表单内动态添加XAML对象,编写可调用的函数实现编程式动态添加XAML表单元素,当前包含两个场景:
- ToggleSwitch点击切换图片
- 点击按钮动态加载Panel面板并刷新窗口
现有场景代码
ToggleSwitch切换图片场景
[xml]$xaml=@" <Window> <Grid x:Name="rootGrid"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ToggleSwitch x:Name="toggleSwitch" Grid.Column="0"/> <Image x:Name="img1" Source="<Source1>" /> <Image x:Name="img2" Source="<Source2>" Visibility="Hidden" /> </Grid> </Window> "@ $toggleSwitch = $syncHash.Window.FindName("toggleSwitch") $toggleSwitch.Add_Click({ # 切换图片仅修改控件可见性即可,WPF会自动刷新UI,无需手动重绘 $img1 = $syncHash.Window.FindName("img1") $img2 = $syncHash.Window.FindName("img2") if($img1.Visibility -eq 'Visible'){ $img1.Visibility = 'Hidden' $img2.Visibility = 'Visible' }else{ $img2.Visibility = 'Hidden' $img1.Visibility = 'Visible' } })
切换图片属于修改已渲染控件的属性,WPF默认会自动同步UI,不需要额外触发窗口刷新。
动态添加XAML面板正确实现
原有代码核心问题
- 直接修改初始XAML的XML对象不会同步到已经渲染的WPF窗口,初始XAML仅为窗口初始化模板,运行时操作需要直接操作已经实例化的WPF控件对象
- 函数定义放在点击事件内部会导致重复定义和递归调用问题
- 不需要手动触发窗口重绘,只要向已渲染的父控件容器添加子控件,WPF会自动更新UI
正确实现代码
# 全局定义可调用的Add-Panel函数 function Add-Panel { [CmdletBinding()] param() # 直接获取已经渲染的根Grid控件(初始XAML需给根Grid加x:Name="rootGrid") $rootGrid = $syncHash.Window.FindName("rootGrid") # 构造要添加的XAML片段,必须声明WPF默认命名空间 $panelXaml = @" <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Grid Grid.Row="8"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label VerticalAlignment="Center" Content="Alternate DNS" FontWeight="Medium" /> </Grid> <Grid Grid.Row="7"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBox x:Name="dns1" Width = "30" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" MaxLength="3" /> <Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="." Grid.Row="0" Grid.Column="1" FontSize="36" FontWeight="Medium"/> <TextBox x:Name="dns2" Width = "30" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Grid.Column="2" MaxLength="3" /> <Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="." Grid.Row="0" Grid.Column="3" FontSize="36" FontWeight="Medium"/> <TextBox x:Name="dns3" Width = "30" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Grid.Column="4" MaxLength="3" /> <Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="." Grid.Row="0" Grid.Column="5" FontSize="36" FontWeight="Medium"/> <TextBox x:Name="dns4" Width = "30" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Grid.Column="6" MaxLength="3" /> </Grid> </Grid> "@ # 将XAML片段转换为WPF可识别的控件对象 $xmlReader = [System.Xml.XmlReader]::Create([System.IO.StringReader]$panelXaml) $newPanel = [System.Windows.Markup.XamlReader]::Load($xmlReader) # 将新控件添加到根Grid,自动刷新UI $rootGrid.Children.Add($newPanel) | Out-Null } # 绑定按钮点击事件 $add.Add_Click({ # UI操作必须放在UI线程Dispatcher中执行,避免跨线程报错 $syncHash.Window.Dispatcher.Invoke([action]{ Add-Panel }, [System.Windows.Threading.DispatcherPriority]::Render) })
内容的提问来源于stack exchange,提问作者user1546559
相关产品推荐
相关产品推荐

