2010-08-06 3 views
0

J'essaie de faire défiler certaines commandes dans une application Powershell/WPF. Rien d'extraordinaire, il suffit de mettre du texte sur un événement mouseEnter.Boucler les contrôles dans WPF/Powershell

Il fonctionne très bien si je ne boucle pas le code:

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

Mais si je tente la même chose en boucle, il met toutes les commandes MouseEnter événements pour définir le texte à « quatre », le dernier élément du tableau:

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

Quelqu'un at-il une idée de la raison de ce problème et comment je peux y remédier?

Merci,

Ben

OK - Ceci est d'autant plus étrange ...

a tenté de répondre à cette aide d'une solution dans le sens de la suggestion de Kent. Je suis la même chose en utilisant $ LocalControl, donc pensé que j'essayer d'utiliser un tableau pour assurer que chaque entrée était distincte:

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

Le comportement que je sais est que se chaque fois que je mouseOver un contrôle, le texte incrémente seulement par le tableau une étape. Par exemple, le premier contrôle que je survole affichera "One", le suivant produira "Two" et ainsi de suite, jusqu'à ce que mon tableau soit épuisé quand il sort juste null.

Cet ordre de sortie «un», «deux», «trois», «quatre» est le même quel que soit l'ordre dans lequel je passe au-dessus des commandes.

... Attendez une minute. Ont mis le $ i = $ i + 1 dans le MouseEnter!

à Modifiée:

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

Définit toutes les sorties à null.

Répondre

1

Vous devez effectuer une fermeture à partir des scriptsblocks. Ce que vous faites face à est comme ceci:

$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 

Donc, si vous faites une fermeture, il pourrait aider:

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

variables dans scriptblock ne sont pas liés au champ d'application où ont été créés. Au lieu de cela ils sont évalués dans la portée actuelle:

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

C'est fantastique - m'avait perplexe! Merci Stej. – Ben

+0

Vous êtes les bienvenus :) Juste curieux .. pourquoi n'utilisez-vous pas certains dsl comme PowerBoots/WPK? – stej

0

Prenez une copie locale de $control:

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

Toutes les références à $control sont résolus après votre boucle terminée, ils se réfèrent tous au dernier élément dans votre collection.

+0

J'ai obtenu la même chose avec $ localControl, donc essayé un tableau. Cela a donné la sortie ci-dessus ... – Ben

Questions connexes