WPF UI 显示组合框项目。控件说它们是空的

问题描述 投票:0回答:1

我对此失去了理智。我正在为 powershell 脚本构建 UI。组合框的 xaml:

<ComboBox x:Name="CB_Failover" Width="172" Margin="5,5,0,0" IsReadOnly="True">
    <ComboBoxItem x:Name="CBI_CBFailover_ALL" Content="All"/>
    <ComboBoxItem x:Name="CBI_CBFailover_core" Content="Core"/>
    <ComboBoxItem x:Name="CBI_CBFailover_wave1" Content="Wave 1"/>
    <ComboBoxItem x:Name="CBI_CBFailover_wave2" Content="Wave 2"/>
    <ComboBoxItem x:Name="CBI_CBFailover_wave3" Content="Wave 3"/>
</ComboBox>

一旦我运行 $synchash.window.showdialog() ,这些项目就会在 UI 中完美显示。但是,当我尝试访问它的控件时,使其有用。这就是我所看到的。 $synchash.cb_failover

ShouldPreserveUserEnteredPrefix : 
IsEditable                      : 
Text                            : 
IsReadOnly                      : 
SelectionBoxItem                : 
SelectionBoxItemTemplate        : 
SelectionBoxItemStringFormat    : 
StaysOpenOnEdit                 : 
IsSelectionBoxHighlighted       : 
IsSynchronizedWithCurrentItem   : 
SelectedIndex                   : 
SelectedItem                    : 
SelectedValue                   : 
SelectedValuePath               : 
Items                           : {, , , …}
etc...

items 属性显示那里有项目,但不知何故它们都是空的。它是一个什么都没有的数组。如果我深入了解项目($synchash.CB_Failover.items),名称和内容的属性为空。我不知道组合框从哪里获取用户界面的信息。如果没有控制。但用户界面显示每个组合框项目的“内容”。我不想太冗长并展示我的整个脚本,因为它很多。我希望组合框中只有一些愚蠢的属性需要添加。

提前致谢。

编辑:

仍然没有弄清楚问题 - 但它是由线程引起的。 我的脚本的开头在新的运行空间中启动它。

$global:syncHash = [hashtable]::Synchronized(@{})
$syncHash.Host = $host;
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()    
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)

$psCmd = [PowerShell]::Create().AddScript({ 
Add-Type -AssemblyName PresentationFramework
$xamlFile = "a personal and private path that holds many secrets"
$inputXML = Get-Content $xamlFile -Raw
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[xml]$XAML = $inputXML

这就是关键点。如果我通过线程执行此操作,控件就会通过,但内容不会。无论我自动还是手动构建所有变量 - 都没关系。 $synchash 将带来控制权,但不会带来其内容。

$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$syncHash.Window=[Windows.Markup.XamlReader]::Load( $reader )
#$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | % {
#    $syncHash.Add($_.Name, $syncHash.Window.FindName($_.name))
#}
$syncHash.Add('CB_Failover', $syncHash.Window.FindName('cb_failover'))

但是,如果我不创建新的运行空间,而只是在全局范围内运行它,则组合框项目的内容不会出现问题。

$xamlFile = "A personal and private path"
$inputXML = Get-Content $xamlFile -Raw
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace             
"x:N", 'N' -replace '^<Win.*', '<Window'
[xml]$XAML = $inputXML

$global:var_CB_Failover = $global:window.FindName('CB_Failover')

输出:

>$global:var_cb_failover.items.content
All    
Core
etc...

那么为什么不同的线程能够拉取控件,但不能拉取该控件内的内容。但是,也能够提取该内容并将其显示在 UI 中吗?

wpf powershell xaml
1个回答
0
投票

所以在深入研究之后 - 抱歉,对这一切真的很陌生。找到一篇多年前写的文章,其中有 boe prox 的解决方案

https://learn-powershell.net/2012/10/14/powershell-and-wpf-writing-data-to-a-ui-from-a- Different-runspace/

TLDR;

内容就在那里,但除非使用调度程序,否则无法从另一个线程中提取它。就我而言,这有效。

$syncHash.CB_Failover.Dispatcher.Invoke([action]{$global:return = 
$syncHash.CB_Failover.items | select -Expand content}) | out-null

输出:

> $return
All
Core
etc...

这真的很令人困惑,因为肯定有很多其他控件、内容等我可以在不使用调度程序的情况下访问。

© www.soinside.com 2019 - 2024. All rights reserved.