我正在尝试遍历Powershell / WPF应用程序中的一些控件。没什么好看的,只需在mouseEnter事件上设置一些文字。
如果我不循环代码,它可以正常工作:
$reader = New-Object System.Xml.XmlNodeReader $xaml
$d = [Windows.Markup.XamlReader]::Load($reader)
$d.FindName("GridOne").add_mouseEnter({
$d.FindName("HelpText").Content = "One"
})
$d.FindName("GridTwo").add_mouseEnter({
$d.FindName("HelpText").Content = "Two"
})
$d.FindName("GridThree").add_mouseEnter({
$d.FindName("HelpText").Content = "Three"
})
$d.FindName("GridFour").add_mouseEnter({
$d.FindName("HelpText").Content = "Four"
})
但如果我尝试与循环相同的东西,它会设置所有控件MouseEnter事件,将文本设置为“Four”,即数组的最后一个元素:
$reader = New-Object System.Xml.XmlNodeReader $xaml
$d = [Windows.Markup.XamlReader]::Load($reader)
$arrControls = ("One","Two","Three","Four")
foreach ($control in $arrControls) {
$d.FindName("Grid$control").add_mouseEnter({
$d.FindName("HelpText").Content = $control
})
}
任何人都有任何想法,为什么会这样,以及如何解决它?
谢谢,
本
好的 - 这甚至更怪......
尝试使用肯特建议的解决方案来解决这个问题。我使用$ localControl也一样,所以我想我会尝试使用数组来确保每个条目都是不同的:
$i = 0
$localControl = @()
foreach ($control in $arrControls) {
$localControl += $control
write-host "$d.FindName('Grid$control').add_mouseEnter({ $d.FindName('HelpText').Content = $control })"
$d.FindName("Grid$control").add_mouseEnter({
$d.FindName("HelpText").Content = $localControl[$i]
$i = $i + 1
})
}
我所知道的行为是,每当我鼠标移动一个控件时,文本只会逐步增加数组。例如,我悬停的第一个控件将输出“One”,下一个将输出“Two”,依此类推,直到我的数组在输出null时耗尽。
这个“一个”,“两个”,“三个”,“四个”输出顺序是相同的,无论我将鼠标悬停在控件上的顺序。
......等一下。已将$ i = $ i + 1放入MouseEnter!
修改为:
$i = 0
$localControl = @()
foreach ($control in $arrControls) {
$localControl += $control
write-host "$d.FindName('Grid$control').add_mouseEnter({ $d.FindName('HelpText').Content = $control })"
$d.FindName("Grid$control").add_mouseEnter({
$d.FindName("HelpText").Content = $localControl[$i]
})
$i = $i + 1
}
将所有输出设置为null。
答案 0 :(得分:1)
您需要从scriptblocks中创建一个闭包。你面临的是这样的:
$i = 1
$block1 = { write-host $i }
$i = 2
$block2 = { write-host $i }
& $block1
& $block2
#---------------- after a change...
$i = 1
$block1 = { write-host $i }.GetNewClosure()
$i = 2
$block2 = { write-host $i }.GetNewClosure()
$i = 3
$block3 = { write-host $i }.GetNewClosure()
& $block1
& $block2
& $block3
所以如果你做一个闭包,它可能会有所帮助:
foreach ($control in $arrControls) {
$d.FindName("Grid$control").add_mouseEnter({
$d.FindName("HelpText").Content = $control
}.GetNewClosure())
}
scriptblock中的变量未绑定到创建的范围。相反,它们在当前范围内进行评估:
PS> $var = 'at beginning'
PS> $writer = { write-host $var }
PS> function test {
$var = 1
& $writer
& {
$var = 10
& $writer
}
}
PS> test
1
10
PS> & $writer
at beginning
答案 1 :(得分:0)
获取$control
的本地副本:
foreach ($control in $arrControls) {
$localControl = $control
$d.FindName("Grid$control").add_mouseEnter({
$d.FindName("HelpText").Content = $localControl
})
}
您的循环完成后,所有对$control
的引用都将得到解决,因此它们都会引用您收藏中的最后一项。