我是WPF新手和使用PowerShell的事件处理,我想要实现的是点击一个按钮,进度条应显示在0-100之间。但是当我运行下面的代码时,它会计算add_click块中的整个代码,它只显示循环中的最后一次迭代。 我知道也许这是一个愚蠢的解决方案,但我确实需要一些帮助。
$syncHash = [hashtable]::Synchronized(@{})
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
$psCmd = [PowerShell]::Create().AddScript({
$XamlPath="C:\Forms\MyFormsv1.xaml"
$inputXML = Get-Content -Path $XamlPath
[xml]$Global:xmlWPF = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
#Add WPF and Windows Forms assemblies
try{
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
} catch {
Throw “Failed to load Windows Presentation Framework assemblies.”
}
$syncHash.Window=[Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF))
[xml]$XAML = $xmlWPF
$xmlWPF.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
$Global:synchash.Add($_.Name,$synchash.Window.FindName($_.Name) )}
function tool1_progress{
$var1=50
for($index=1 ; $index -le $var1; $index++)
{
[int]$tmpProgNum= ($index/$var1) * 100
$syncHash.tool1_pb.Value= $tmpProgNum
$syncHash.consoleOutput.Text=$index
Start-Sleep -Milliseconds 250
}
}
$syncHash.myButton.add_click({tool1_progress})
$syncHash.Window.ShowDialog() | out-null
})
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()
$ tool1是一个标签。 $ tool1_pb是一个进度条。 $ consoleOutput是一个 文本框。
答案 0 :(得分:0)
我一直在集成WPF和PowerShell。 This网站对我帮助很大。您无法更新在同一线程上运行的UI,因此您需要使用BeginInvoke()
$psCmd = [PowerShell]::Create().AddScript({
$Global:uiHash.Error = $Error
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase
$xaml = @"YOURXAMLHERE"
$Global:uiHash.Window=[Windows.Markup.XamlReader]::Parse($xaml )
[xml]$XAML = $xaml
$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
$Global:uihash.Add($_.Name,$uihash.Window.FindName($_.Name) )}
$Global:uiHash.Window.ShowDialog() | out-null
})
$psCmd.Runspace = $newRunspace
$handle = $psCmd.BeginInvoke()
然后,为了更新您需要的内容,您将使用Window.Dispatcher.Invoke
$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.Window.Title = "MyWindowTitle"},"Normal")
修改
$Global:uiHash.Button1.Add_Click(tool1_progress)
编辑
投入您的XML,这将有效。您必须在另一个之上创建另一个运行空间,以便不断更新文本框和进度条。请注意,synchash
必须是$Global:synchash
。功能由this post.
$Global:syncHash = [hashtable]::Synchronized(@{})
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
$psCmd = [PowerShell]::Create().AddScript({
$XamlPath="C:\Forms\MyFormsv1.xaml"
$inputXML = @"YOURXMLHERE"@
[xml]$Global:xmlWPF = $inputXML
#Add WPF and Windows Forms assemblies
try{
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
} catch {
Throw “Failed to load Windows Presentation Framework assemblies.”
}
$Global:syncHash.Window=[Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF))
[xml]$XAML = $xmlWPF
$xmlWPF.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
$Global:synchash.Add($_.Name,$Global:syncHash.Window.FindName($_.Name) )}
function Start-Runspace{
param($scriptblock)
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("SyncHash",$global:synchash)
$psCmd = [PowerShell]::Create().AddScript($ScriptBlock)
$psCmd.Runspace = $newRunspace
$psCMD.BeginInvoke()
}
$SB = {
$var1=50
for($index=1 ; $index -le $var1; $index++)
{
[int]$tmpProgNum= ($index/$var1) * 100
$Global:syncHash.Window.Dispatcher.Invoke([action]{$Global:Synchash.tool1_pb.value = "$tmpprognum"},"Normal")
$Global:syncHash.Window.Dispatcher.Invoke([action]{$Global:Synchash.consoleoutput.text = "$index"},"Normal")
Start-Sleep -Milliseconds 250
}
}
$Global:syncHash.myButton.add_click({Start-Runspace $SB})
$Global:syncHash.Window.ShowDialog() | out-null
})
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()
start-sleep -Milliseconds 300