2010-08-06 182 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