我对此失去了理智。我正在为 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 中吗?
所以在深入研究之后 - 抱歉,对这一切真的很陌生。找到一篇多年前写的文章,其中有 boe prox 的解决方案
TLDR;
内容就在那里,但除非使用调度程序,否则无法从另一个线程中提取它。就我而言,这有效。
$syncHash.CB_Failover.Dispatcher.Invoke([action]{$global:return =
$syncHash.CB_Failover.items | select -Expand content}) | out-null
输出:
> $return
All
Core
etc...
这真的很令人困惑,因为肯定有很多其他控件、内容等我可以在不使用调度程序的情况下访问。