2010-08-06 175 views
0

我想通过Powershell/WPF应用程序中的某些控件循环。没有什么奇特的,只是在mouseEnter事件上设置一些文本。循环浏览WPF/Powershell中的控件

,如果我不循环的代码工作正常:

$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事件设置文本为“四”的所有控件,阵列的最后一个元素:

$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 
    }) 
} 

任何人有任何想法,为什么这是,我怎么能解决它?

感谢,

OK - 这是更加古怪......

尝试使用沿着肯特的建议通过一项解决方案来解决这个问题。我得到了使用$本地控制一样,所以想我会尝试使用阵列,以确保每一个条目是不同的:

$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。

回答

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()) 
} 

变量不绑定到那里创建范围。相反,他们在当前的范围进行了评估:

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 
+0

这太棒了 - 让我难住了!感谢Stej。 – Ben 2010-08-06 11:10:48

+0

欢迎:)只是好奇......你为什么不使用PowerBoots/WPK等一些dsl? – stej 2010-08-06 11:38:28

0

以一个本地副本的$control:你的循环完成后

foreach ($control in $arrControls) { 
    $localControl = $control 
    $d.FindName("Grid$control").add_mouseEnter({ 
     $d.FindName("HelpText").Content = $localControl 
    }) 
} 

$control所有文献都被解决,所以他们都指的是最后一个项目你的收藏。

+0

我得到了同样的$ localControl,所以尝试了一个数组。这给了上面的输出...... – Ben 2010-08-06 09:24:01